#c# #wcf #threadabortexception #thread-abort
#c# #wcf ( ВКФ ) #исключение threadabortexception #прерывание потока
Вопрос:
У меня есть служба WCF (встроенная в .NET framework 3.5), размещенная на IIS 6.0.
Поток кода выглядит следующим образом
- Клиент (который является другим веб-сервисом) вызывает службу WCF
- Службы WCF вызывают поток для выполнения обработки в фоновом режиме и немедленно отвечают вызываемому.
- Фоновый поток после завершения всей обработки вызывает поток обратно. Этот вызов в основном представляет собой HTTPs-запрос, поскольку клиент является веб-сервисом.
Я провожу нагрузочное тестирование своего сервиса WCF, чтобы определить пороговые значения. Наблюдение заключается в следующем:
Около 3 итераций из 1024 запросов, отправленных в службу WCF в течение 1 минуты, проходят успешно. Время, затрачиваемое на выполнение каждой итерации, составляет около 25-30 минут. Однако с 4-й итерации видны массовые сбои. Около 50% запросов завершаются неудачей с приведенным ниже исключением.
Исключение -Поток был прерван.
Трассировка стека
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(TransportContextamp; 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.
Где бы ни использовались потоки, у меня есть dispose во всех местах. Таким образом, все потоки закрыты.
Кто-нибудь может сказать мне, кто прерывает потоки и почему, и есть ли какие-либо средства или инструмент для отслеживания причины инициирования прерывания потока?
Комментарии:
1. Возможно ли, что Клиент прерывает запрос, потому что это также сгенерирует исключение на стороне сервера
2. ASP.NET порождает и убивает рабочие процессы постоянно по мере необходимости. Возможно, ваш поток просто закрывается из-за ASP.NET . Узнайте, сколько потоков может быть запущено одновременно на вашем компьютере. Также попробуйте отследить производительность процессора во время тестирования.
3. Вы увеличили объем объединенных вызовов, но не увеличили размер буфера. У меня такое чувство, что из-за этого многие звонки прекращаются.
4. Какая служба регистрирует ошибку? Клиентская служба или служба WCF?
Ответ №1:
Я столкнулся с этой проблемой, и она была вызвана неправильным использованием клиентского класса.
Что происходило, так это то, что при создании экземпляра клиентского класса он не освобождал ресурсы обратно, что приводило к снижению пропускной способности. Возникло бы очень бесполезное исключение «Поток был прерван». Это было решено путем создания вспомогательного класса, который generically создал клиентский объект, а затем правильно реализовал конструктор и метод dispose.
Некоторые исключения IIS не очень полезны или соответствуют фактической причине проблемы, но чтобы разобраться в том, что было сделано для решения моей проблемы, нужно было просмотреть журналы IIS. В частности, «Правила отслеживания неудачных запросов«
Надеюсь, это поможет, я могу понять ваше разочарование, решить которое было головной болью.
Ответ №2:
Я уже сталкивался с тем же самым раньше. Решение состояло в том, чтобы освободить ресурсы / клиент после завершения его области действия путем реализации метода Dispose.
Проблема существует, поскольку инструкция C # using
для автоматической очистки ресурсов при использовании типизированного клиента не выполняется успешно, и любое генерируемое исключение маскируется неявным dispose, который использует фактическое исключение и выдает какое-либо другое исключение, такое как тайм-аут или другие исключения.
Оператор C # «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
}
Источники :
Комментарии:
1. Извините за задержку с ответом. Большое вам спасибо за уделенное время, ребята. Поскольку я хотел, чтобы проблема была устранена как можно скорее, одним из способов решения проблемы было увеличение размера оперативной памяти компьютера, который устранил проблему.