Подтвердить что ты не робот

Потоковые прерванные исключения в wcf-сервисе

У меня есть служба WCF (встроенная .NET Framework 3.5), размещенная на IIS 6.0.

Поток кода выглядит следующим образом

  • Клиент (который является другим веб-сервисом) вызывает службу WCF
  • Службы WCF вызывают поток для обработки в фоновом режиме и немедленно реагируют на вызываемого абонента.
  • Фоновый поток после завершения всей обработки вызывает обратный поток. Этот вызов в основном является запросом HTTP, поскольку клиент является веб-службой.

Я загружаю свою службу WCF для определения пороговых значений. Наблюдение выглядит следующим образом:

Примерно три итерации 1024 запросов, сделанных в службу WCF за 1 минуту, проходят успешно. Время, затраченное на выполнение каждой итерации, составляет около 25-30 минут. Однако из 4-го итерационного сбоя. Около 50% запросов терпят неудачу с приведенным ниже исключением.

Исключение-Thread прерывается.

Трассировка стека

21_10_2016_09_30_52,9:30:52 AM,Information,Thread name- apSwTTbLTETfwT3y Stack trace in ProcessTestConversion method -    at System.Threading.WaitHandle.WaitOneNative(SafeHandle waitableSafeHandle, UInt32 millisecondsTimeout, Boolean hasThreadAffinity, Boolean exitContext)
   at System.Threading.WaitHandle.InternalWaitOne(SafeHandle waitableSafeHandle, Int64 millisecondsTimeout, Boolean hasThreadAffinity, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne(Int32 millisecondsTimeout, Boolean exitContext)
   at System.Net.LazyAsyncResult.WaitForCompletion(Boolean snap)
   at System.Net.Connection.SubmitRequest(HttpWebRequest request, Boolean forcedsubmit)
   at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName)
   at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()
   .
   .(My function calls stack trace)
   .
   .

Изменения, которые я попытался решить, следующие проблемы:

   <behavior>
    <serviceThrottling maxConcurrentCalls="2000"
                                 maxConcurrentInstances ="2400"
                                 maxConcurrentSessions ="400"/>
    </behavior>

в web.config

<system.web>
        <compilation debug="false" />
        <httpRuntime executionTimeout="1800"/>
    </system.web>

в web.config

  <system.net>
        <connectionManagement>
          <add address = "*" maxconnection = "100" />
        </connectionManagement>
      </system.net>

в web.config

ServicePointManager.DefaultConnectionLimit = 100; (Change in code)

Я установил свойство IdleTimeout для пула приложений равным 0, как было предложено многими людьми в StackOverflow.

Когда бы ни использовались потоки, я располагался во всех местах. Итак, все потоки закрыты.

Может ли кто-нибудь сказать мне, кто прерывает потоки и почему и есть ли какие-либо средства или инструмент для отслеживания причины инициирования прерывания потока?

4b9b3361

Ответ 1

Я столкнулся с этой проблемой, и это было связано с неправильным использованием класса клиента.

Что происходит, когда экземпляр класса клиента был создан, он не освободит ресурсы, что приведет к снижению пропускной способности. Возникло очень бесполезное исключение "Прерывание нити". Это было разрешено созданием класса-помощника, который общий создавал клиентский объект, а затем реализовал конструктор и правильно утилизировал метод.

Некоторые исключения IIS не очень полезны или истинны для фактической причины проблемы, но для того, чтобы понять, что было сделано для решения моей проблемы, нужно посмотреть журналы IIS. В частности, "" Ошибочные правила трассировки запроса"

Надеюсь, это поможет, я могу понять ваше разочарование, чтобы устранить головную боль.

Ответ 2

Я уже сталкивался с этим раньше. Решение заключалось в том, чтобы освободить ресурсы/клиент после того, как его область была завершена, реализовав метод Dispose.

Проблема существует, так как оператор С# using для автоматической очистки ресурсов при использовании типизированного клиента не увенчался успехом, и любое вызванное исключение маскируется неявным распоряжением, которое ест реальное исключение и выдает другое исключение, такое как тайм-аут или другие исключения.

Оператор С# "using" приводит к вызову Dispose(). Это то же самое, что и Close(), что может вызвать исключения при возникновении сетевой ошибки. Поскольку вызов Dispose() происходит неявно в закрывающей скобке блока "using", этот источник исключений, вероятно, останется незамеченным как людьми, записывающими код, так и чтением кода. Это представляет собой потенциальный источник ошибок приложения. (от MSDN)

Вы должны освободить ресурсы, например:

try
{
    ...
    client.Close();
}
catch (CommunicationException e)
{
    ...
    client.Abort();
}
catch (TimeoutException e)
{
    ...
    client.Abort();
}
catch (Exception e)
{
    ...
    client.Abort();
    throw;
}

Таким образом, вы можете не только найти фактический источник исключения, но и освободить ресурс, когда произойдет некоторая операция.

Другое альтернативное решение может реализовать Dispose как:

/// <summary>
/// Calculator Client
/// </summary>
public partial class CalculatorClient : IDisposable
{
    #region IDisposable implementation

    /// <summary>
    /// IDisposable.Dispose implementation, calls Dispose(true).
    /// </summary>
    void IDisposable.Dispose()
    {
        Dispose(true);
    }

    /// <summary>
    /// Dispose worker method. Handles graceful shutdown of the
    /// client even if it is an faulted state.
    /// </summary>
    /// <param name="disposing">Are we disposing (alternative
    /// is to be finalizing)</param>
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            try
            {
                if (State != CommunicationState.Faulted)
                {
                    Close();
                }
            }
            finally
            {
                if (State != CommunicationState.Closed)
                {
                    Abort();
                }
            }
        }
    }

    /// <summary>
    /// Finalizer.
    /// </summary>
    ~CalculatorClient()
    {
        Dispose(false);
    }

    #endregion
}

Источники:

Избежать проблем с использованием инструкции MSDN

Использование и удаление клиентов WCF