Максимальное количество одновременных сеансов для WCF с использованием методов IIS и Asynch - освобождение ресурсов - PullRequest
0 голосов
/ 17 сентября 2011

Я звоню в службу WCF из формы. Сервис размещен в IIS. Служба со следующими атрибутами: InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple

Я установил максимальный режим регулирования на 2000 для всех одновременных вызовов, экземпляров и сеансов.

Однако я не могу получить более 200 запросов ASynch. После этого служба просто не отвечает, и время сеанса заканчивается.

Я использую вызов Asynch для вызова метода в службе, т.е. Свернуть | Скопировать код

IASyncResult res = Proxy.BeginMethod (endCall, null);

и затем для получения ответа у меня есть функция endCall, которая принимает IASyncResult и обрабатывает результат через EndMethod ().

в методе имитации загрузки @ 1 вызов в секунду, все работает нормально до примерно 200 вызовов, а затем просто ждет ... (У меня есть 199 или 198 ответов от этих 200 вызовов в данный момент времени) .. - так что теоретически не должно быть 200 одновременных сессий, только 2 или около того ..

Возможно, есть какая-то сборка мусора или закрытие, которое я не делаю? какие-либо предложения?

---- обновление ---

Я думаю, что ответ может быть еще больше, что закрытие прокси не обрабатывается потокобезопасным способом. Как указывает Radik выше, закрытие прокси-сервера очень важно, однако при одновременном поступлении многих результатов IASyncState необходимо убедиться, что вы закрыли нужный в нужное время.

Я попытался запустить закрытый прокси из потока, чтобы он мог обрабатывать его отдельно:

ThreadPool.QueueUserWorkItem (CloseProxy, ar.AsyncState);

но это не похоже на работу. Есть предложения по этому поводу?

1 Ответ

1 голос
/ 18 сентября 2011

Когда вы создаете ссылку на службу в 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);
}
...