如何处理处于故障状态的 WCF 服务客户端?
What to do with a WCF service client in faulted state?
我使用 WCF 服务异步。如果我无法连接到该服务或发生异常,它将进入故障状态并将错误写入 AsyncCompletedEventArgs
的 Error
属性。
服务客户端和我有什么关系?我无法关闭它,因为它会抛出 CommunicationObjectFaultedException
。记录错误后我还需要做什么?
这是我的代码:
MyServiceClient serviceClient = new MyServiceClient();
//Close the connection with the Service or log an error
serviceClient.JustAMethod += (object sender, AsyncCompletedEventArgs args) =>
{
if (args.Error != null)
{
//Log error
ErrorHandler.Log(args.Error);
}
else
{
serviceClient.Close();
}
};
//Call the service
serviceClient.JustAMethodAsync();
您无能为力。创建一个新的,让垃圾收集器收集另一个。
您可以中止它,然后创建一个新的。这是我写的 class 中处理该问题的片段。当客户端处于故障状态时,它在这里接触的所有东西都是合法的。
if (_client.InnerChannel.State == CommunicationState.Faulted)
{
_client.Abort();
_client = new TServiceClient();
}
TServiceClient
是 System.ServiceModel.ClientBase<TIClientInterface>
的任何子 class。
我之所以这样写,是因为在浏览器客户端通过 RDS 访问页面的情况下,从 MVC4 网络应用程序的服务器端调用网络服务时,我一直遇到访问问题。
但是,到目前为止,上面的代码还没有被使用。由于我不明白的原因,它比最简单的代码有更多的拒绝访问异常总是为每次调用创建一个新客户端并在之后处理它的方法。我从不费心检查故障状态,因为无论如何我都不会将它们用于多个调用。
using (var cli = new Blah.Blah.FooWCFClient())
{
_stuff = cli.GetStuff();
}
...当然是 try/catch。如果您发现 client-caching/Abort 方法有任何问题,我建议您尝试为每次调用创建一个新客户端。也许它会花费几个周期,但是调用 Web 服务然后 然后 开始担心运行时效率是很愚蠢的。那匹马离开了谷仓。
我不知道这将如何与异步业务交互,除了关于保持简单并且不跨线程共享任何内容的模糊直觉。
欢迎来到我的噩梦。我还没有确定我们的访问问题的原因,但我怀疑事情可能对你来说那么糟糕。所以我希望这两个选项中至少有一个会成功。
更新
这是我们的 XAML 应用程序中一些 .tt 生成的服务包装器代码。每个 Web 服务调用方法都像这样包装,多年来一直是防弹的。我建议基本上这样做:
public static POCO.Thing GetThing(int thingID)
{
var proxy = ServiceFactory.CreateNewFooWCFClientInstance();
try
{
var returnValue = proxy.GetThing(thingID);
proxy.Close();
return returnValue;
}
catch(Exception ex)
{
// ***********************************
// Error logging boilerplate redacted
// ***********************************
proxy.Abort();
throw;
}
}
我觉得如果您根本不重用 WCF 客户端对象也一样。
我使用 WCF 服务异步。如果我无法连接到该服务或发生异常,它将进入故障状态并将错误写入 AsyncCompletedEventArgs
的 Error
属性。
服务客户端和我有什么关系?我无法关闭它,因为它会抛出 CommunicationObjectFaultedException
。记录错误后我还需要做什么?
这是我的代码:
MyServiceClient serviceClient = new MyServiceClient();
//Close the connection with the Service or log an error
serviceClient.JustAMethod += (object sender, AsyncCompletedEventArgs args) =>
{
if (args.Error != null)
{
//Log error
ErrorHandler.Log(args.Error);
}
else
{
serviceClient.Close();
}
};
//Call the service
serviceClient.JustAMethodAsync();
您无能为力。创建一个新的,让垃圾收集器收集另一个。
您可以中止它,然后创建一个新的。这是我写的 class 中处理该问题的片段。当客户端处于故障状态时,它在这里接触的所有东西都是合法的。
if (_client.InnerChannel.State == CommunicationState.Faulted)
{
_client.Abort();
_client = new TServiceClient();
}
TServiceClient
是 System.ServiceModel.ClientBase<TIClientInterface>
的任何子 class。
我之所以这样写,是因为在浏览器客户端通过 RDS 访问页面的情况下,从 MVC4 网络应用程序的服务器端调用网络服务时,我一直遇到访问问题。
但是,到目前为止,上面的代码还没有被使用。由于我不明白的原因,它比最简单的代码有更多的拒绝访问异常总是为每次调用创建一个新客户端并在之后处理它的方法。我从不费心检查故障状态,因为无论如何我都不会将它们用于多个调用。
using (var cli = new Blah.Blah.FooWCFClient())
{
_stuff = cli.GetStuff();
}
...当然是 try/catch。如果您发现 client-caching/Abort 方法有任何问题,我建议您尝试为每次调用创建一个新客户端。也许它会花费几个周期,但是调用 Web 服务然后 然后 开始担心运行时效率是很愚蠢的。那匹马离开了谷仓。
我不知道这将如何与异步业务交互,除了关于保持简单并且不跨线程共享任何内容的模糊直觉。
欢迎来到我的噩梦。我还没有确定我们的访问问题的原因,但我怀疑事情可能对你来说那么糟糕。所以我希望这两个选项中至少有一个会成功。
更新
这是我们的 XAML 应用程序中一些 .tt 生成的服务包装器代码。每个 Web 服务调用方法都像这样包装,多年来一直是防弹的。我建议基本上这样做:
public static POCO.Thing GetThing(int thingID)
{
var proxy = ServiceFactory.CreateNewFooWCFClientInstance();
try
{
var returnValue = proxy.GetThing(thingID);
proxy.Close();
return returnValue;
}
catch(Exception ex)
{
// ***********************************
// Error logging boilerplate redacted
// ***********************************
proxy.Abort();
throw;
}
}
我觉得如果您根本不重用 WCF 客户端对象也一样。