如何检测WCF客户端何时无法正常关闭?

时间:2015-08-13 22:21:32

标签: c# wcf

我试图弄清楚我们使用过多次使用过的WCF服务时遇到的问题。它偶尔会变得反应迟钝,从而使我们的几个依赖该服务的内部网站无法使用。

我们怀疑它是因为一个或多个消费网站未能正确关闭连接,因此我们对服务上允许的并发连接数量进行了限制。然而,我们没有实际的方法来确定哪一个,因为在多个tfs存储库中有这么多。

简而言之,当客户端在wcf代理上调用Close()时,如何从服务中检测到?或者,在服务方法完成后,如何检测http连接是否仍处于打开状态?

我已经在我的本地工作站上创建了一个测试服务和客户端并尝试了以下操作,但没有一个工作正常:

测试服务:

public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
}

测试客户端:

class Program
{
    static void Main(string[] args)
    {
        ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
        Console.WriteLine(client.GetData(0));
        Console.ReadKey();
        client.Close();
        Console.WriteLine("Closed.");
        Console.ReadKey();
    }
}

运行netstat表明,即使在client.Close()之后,连接仍然保持打开状态(也许我只是误解了netstat的输出)。

perfmon性能计数器(在添加ServiceModelService 4.0.0.0之后)报告甚至在client.Close()执行之前服务调用已完成。在服务调用之后,client.Close()之前和之后的计数器没有变化。

接下来,我尝试收听OperationContext.Current.Channel.Closed事件(以及Closing和Faulted):

public class Service1 : IService1
{
    public string GetData(int value)
    {
        OperationContext.Current.Channel.Faulted += Channel_Faulted;
        OperationContext.Current.Channel.Closing += Channel_Closing;
        OperationContext.Current.Channel.Closed += Channel_Closed;
        return string.Format("You entered: {0}", value);
    }

    void Channel_Faulted(object sender, EventArgs e)
    {
        // Breakpoint
    }

    void Channel_Closing(object sender, EventArgs e)
    {
        // Breakpoint
    }

    void Channel_Closed(object sender, EventArgs e)
    {
        // Breakpoint
    }
}

但是我在事件处理程序中放置的断点都没有被击中。

我还尝试在Global.asax的Session_Start和Session_End事件中添加断点。 Session_Start会触发,但Session_End从不会触发(虽然我不知道会话是否与http连接是否存在有关)。

我对wcf有点新鲜(之前我写了几个非常基本的服务)所以我觉得我在这个问题上有点过头了,挖掘我不喜欢的部分。理解(例如,我今天之前并不知道OperationContext存在)。

1 个答案:

答案 0 :(得分:0)

您应该在调用服务时处理异常,否则通道无法正常关闭。

例如:from here

    WCFServiceClient c = new WCFServiceClient();

    try
    {
            c.HelloWorld();
    }
    catch
    {
            c.Abort();
            throw;
    }
    finally
    {
            c.Close();
    }

(还有一个例子,'使用'如果愿意的话)。

还要看here