0

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

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

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

我正在使用异步调用来调用服务中的方法,即 复制代码

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

然后为了捕捉响应,我有一个 endCall 函数,它接收 IASyncResult 并通过 EndMethod() 处理结果。

在负载模拟@ 1 方法调用一秒钟,一切正常,直到大约 200 个调用,然后只是等待......(此时我有 199 或 198 个来自这 200 个调用的响应).. - 所以理论上存在不应该是 200 个并发会话,只有 2 个左右..

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

- - 更新 - -

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

我确实尝试从一个线程中触发关闭代理以让它单独处理它:

ThreadPool.QueueUserWorkItem(CloseProxy, ar.AsyncState);

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

4

1 回答 1

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);
}
于 2011-09-17T21:22:11.650 回答