使用IIS和Asynch方法的WCF最大并发会话 - 释放资源

时间:2011-09-17 17:26:06

标签: c# .net wcf concurrency asynchronous-wcf-call

我从表单调用WCF服务。服务托管在IIS中。具有以下属性的服务:InstanceContextMode.PerSession,ConcurrencyMode = ConcurrencyMode.Multiple

对于所有并发调用,实例和会话,我已将限制行为设置为最大值2000。

但是我似乎无法获得超过200个ASynch请求。之后服务就没有响应,会话最终会超时。

我正在使用Asynch调用来调用服务中的方法,即 折叠|复制代码

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

然后要捕获响应我有一个endCall函数,它接受IASyncResult并通过EndMethod()处理结果。

在一个负载模拟@ 1方法中调用第二个,一切正常,直到大约200个调用,然后等待......(此时我从这200个调用中得到199或198个响应).. - 所以从理论上讲,不应该有200个并发会话只有2个左右。

也许有一些我不做的垃圾收集或关闭? 有什么建议?

---- ---更新

我认为答案可能更多的是代理的关闭不是以线程安全的方式处理的。正如Radik指出的那样,关闭代理很重要,但是当许多IASyncState结果同时进入时,你必须确保在正确的时间关闭正确的结果。

我尝试从一个线程中解雇close代理,让它单独处理它:

ThreadPool.QueueUserWorkItem(CloseProxy,ar.AsyncState);

但这似乎不起作用。对此有何建议?

1 个答案:

答案 0 :(得分:1)

在VS中创建服务引用时,生成的代理允许您通过两种方式使用回调或事件处理程序异步调用服务。还有两个不同的地方可以关闭代理。 小样本项目here

//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);
}