Skip to main content
 首页 » 编程设计

c#之我应该如何处理从 WCF 回调接口(interface)对象集合之一抛出的异常

2024年01月02日31虾米哥

更新: 自从写了这个问题,我遇到了这个 Bug Report它提供了一种方法来复制我一直看到的错误的症状。

我还不能确认这是否是我遇到的错误的原因,但它值得一些调查。我还没有找到解决报告中描述的错误的方法。

报告总结:如果 WCF 客户端在 WCF 服务的身份验证期间关闭,则会在该服务上抛出一个异步异常,(在我的例子中)直到它到达 program.cs 文件时才会被捕获,因此使它成为很难优雅地处理。

原始问题:

我在 Windows 服务中托管了一个 WCF 服务。

WCF 服务允许客户端订阅(提供回调),之后,该服务向所有订阅者发布更新。

该服务维护一个 Dictionary<int, ICallback>所有当前订阅者的回调接口(interface)。

当需要发布信息的事件发生时,服务循环遍历集合并调用 ICallback 中定义的适当方法。

这一切工作正常,所有使用 ICallback 对象的场合都包含在 try catch 中,以防对象处置异常和任何其他可能发生的异常。

我遇到的问题是在服务中引发了通信异常:

System.ServiceModel.CommunicationException:

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue.

Local socket timeout was '10675199.02:48:05.4775807'.

System.IO.IOException: The read operation failed, see inner exception.

System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue.

Local socket timeout was '10675199.02:48:05.4775807'.

System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

此异常未被捕获并导致应用程序崩溃。

因为它没有被捕获,所以我假设在服务尝试发布数据时没有抛出异常,因为这总是发生在 try - catch 中。

此异常是否可能是客户端应用程序错误地关闭了 channel /套接字引起的?

更重要的是,当正在运行的线程中当前未访问引发异常的对象时,如何捕获以这种方式引发的异常?

即抛出异常时,ICallback 对象位于字典中,未被使用 - 那么如何处理异常?我应该把 try catch 放在哪里?

WCF 服务订阅方法

public static int Subscribe() 
{ 
    int id = -1; 
 
    OperationContext currentContext = OperationContext.Current; 
 
    if (currentContext != null) 
    { 
        ICallback callback = currentContext.GetCallbackChannel<ICallback>(); 
 
        if (callback != null) 
        { 
            id = GetNextId(); 
 
            lock (SubscriberLock) 
            { 
                Subscribers.Add(id, callback); 
            } 
        } 
    } 
    return id; 
} 

在该方法完成后的一段时间内抛出异常。

我不太高兴我已经非常清楚地解释了这个问题,所以如果有一个特定的点不是很清楚,请要求澄清。

谢谢!

请您参考如下方法:

通信异常将在客户端抛出,而不是在 WCF 端。 您可以通过将通信异常包装在 try 和 catch 中来在客户端捕获通信异常。 CommunicationException 是在 wcf 中生成的所有异常的基类型。您还应该将日志记录添加到您的 wcf 服务和客户端。详细如何添加日志 here.