Максимальное количество одновременных сеансов для WCF с использованием методов IIS и Asynch - освобождение ресурсов
Я звоню в службу WCF из формы. Сервис размещен в IIS. Служба со следующими атрибутами: InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple
Я установил режим регулирования на максимум в 2000 для всех одновременных вызовов, экземпляров и сеансов.
Однако я не могу получить более 200 запросов ASynch. После этого служба просто не отвечает, и время сеанса заканчивается.
Я использую вызов Asynch для вызова метода в сервисе, т.е. Collapse | Скопировать код
IASyncResult res= Proxy.BeginMethod(endCall,null);
и затем, чтобы поймать ответ, у меня есть функция endCall, которая принимает IASyncResult и обрабатывает результат через EndMethod().
при вызове метода имитации загрузки @ 1 в секунду все работает нормально, пока не произойдет около 200 вызовов, а затем просто ждет... (у меня есть 199 или 198 ответов от этих 200 вызовов в данный момент времени).. - так что теоретически НЕ должно быть 200 одновременных сессий только 2 или около того..
Возможно, есть какая-то сборка мусора или закрытие, которое я не делаю? какие-либо предложения?
----Обновить---
Я думаю, что ответ может быть больше, что закрытие прокси не обрабатывается потокобезопасным способом. Как указывает Radik выше, закрытие прокси-сервера важно, однако при одновременном поступлении многих результатов IASyncState необходимо убедиться, что вы закрыли нужный в нужное время.
Я попытался запустить закрытый прокси из потока, чтобы он мог обрабатывать его отдельно:
ThreadPool.QueueUserWorkItem (CloseProxy, ar.AsyncState);
но это не похоже на работу. Есть предложения по этому поводу?
1 ответ
При создании ссылки на службу в VS сгенерированный прокси-сервер позволяет асинхронно вызывать службу двумя способами с помощью обратного вызова или обработчика событий. И два разных места, где можно закрыть прокси. маленький пример проекта здесь
//close proxy in callback function
private void ButtonCallbackClick(object sender, EventArgs e)
{
var proxy = new ServiceClient("BasicHttpBinding_IService");
proxy.BeginDoWork(DateTime.Now.ToShortDateString(), CallBack, proxy);
}
private void CallBack(IAsyncResult ar)
{
var result = (ar.AsyncState as ServiceClient).EndDoWork(ar);
if (ar.IsCompleted)
UpdateView(result);
CloseProxy(ar.AsyncState);
}
//close proxy in event handler
private void ButtonCompletedClick(object sender, EventArgs e)
{
var proxy = new ServiceClient("BasicHttpBinding_IService");
proxy.DoWorkAsync(DateTime.Now.ToShortDateString());
proxy.DoWorkCompleted += DoWorkCompleted;
}
private void DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
{
if (e.Error == null)
UpdateView(e.Result);
CloseProxy(sender);
}
private static void CloseProxy(object sender)
{
var proxy = sender as ServiceClient;
if (proxy == null) return;
try
{
proxy.Close();
}
catch (CommunicationException e)
{
proxy.Abort();
}
catch (TimeoutException e)
{
proxy.Abort();
}
catch (Exception e)
{
proxy.Abort();
}
}
private static bool _run = false;
//run async query in infinite cycle
private void ButtonCycleClick(object sender, EventArgs e)
{
_run = !_run;
if (!_run) return;
Action<object> action = WaitEvent;
ThreadPool.QueueUserWorkItem(a => action(action));
}
private void WaitEvent(object action)
{
var proxy = new ServiceClient("BasicHttpBinding_IService");
proxy.DoWorkAsync(DateTime.Now.ToShortDateString());
proxy.DoWorkCompleted += (x, y) => DoWorkCompleted(x, y, action as Action<object>);
}
private void DoWorkCompleted(object sender, DoWorkCompletedEventArgs e, Action<object> action)
{
if (!_run)
return;
if (e.Error == null)
UpdateView(e.Result);
CloseProxy(sender);
action(action);
}