什么是WCF客户端`using`阻止问题的最佳解决方法吗? [英] What is the best workaround for the WCF client `using` block issue?

查看:135
本文介绍了什么是WCF客户端`using`阻止问题的最佳解决方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢实例化我的WCF服务客户端使用块中,因为它是pretty多的使用实现资源的标准方法 IDisposable的

I like instantiating my WCF service clients within a using block as it's pretty much the standard way to use resources that implement IDisposable:

using (var client = new SomeWCFServiceClient()) 
{
    //Do something with the client 
}

不过,在注意到了这MSDN文章,包裹在WCF客户端使用块可能会掩盖导致客户端的任何错误被留在故障状态(如超时或沟通问题)。长话短说,在处置()被调用,客户端的Close()方法火灾,但由于它在故障状态抛出一个错误。原始异常然后由第二异常屏蔽。不好。

But, as noted in this MSDN article, wrapping a WCF client in a using block could mask any errors that result in the client being left in a faulted state (like a timeout or communication problem). Long story short, when Dispose() is called, the client's Close() method fires, but throws an error because it's in a faulted state. The original exception is then masked by the second exception. Not good.

在MSDN文章中建议的解决方法是完全避免使用使用块,并以实例化,而不是你的客户,并利用它们是这样的:

The suggested workaround in the MSDN article is to completely avoid using a using block, and to instead instantiate your clients and use them something like this:

try
{
    ...
    client.Close();
}
catch (CommunicationException e)
{
    ...
    client.Abort();
}
catch (TimeoutException e)
{
    ...
    client.Abort();
}
catch (Exception e)
{
    ...
    client.Abort();
    throw;
}

相比于使用

,我认为这是丑陋的。和很多code的每一个你需要一个客户端的时间写的。

Compared to the using block, I think that's ugly. And a lot of code to write each time you need a client.

幸运的是,我发现了一些其他解决方法,像这样一个在<一个href=\"http://www.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx\">IServiceOriented.你开始:

Luckily, I found a few other workarounds, such as this one on IServiceOriented. You start with:

public delegate void UseServiceDelegate<T>(T proxy); 

public static class Service<T> 
{ 
    public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>(""); 

    public static void Use(UseServiceDelegate<T> codeBlock) 
    { 
        IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel(); 
        bool success = false; 
        try 
        { 
            codeBlock((T)proxy); 
            proxy.Close(); 
            success = true; 
        } 
        finally 
        { 
            if (!success) 
            { 
                proxy.Abort(); 
            } 
        } 
     } 
} 

然后允许:

Service<IOrderService>.Use(orderService => 
{ 
    orderService.PlaceOrder(request); 
}); 

这不是坏事,但我不认为这是因为前pressive易懂的使用块。

blog.davidbarret.net 目前,我试图用我第一次读到的解决方法。基本上你覆盖客户机的无论你使用它的Dispose()方法。是这样的:

The workaround I'm currently trying to use I first read about on blog.davidbarret.net. Basically you override the client's Dispose() method wherever you use it. Something like:

public partial class SomeWCFServiceClient : IDisposable
{
    void IDisposable.Dispose() 
    {
        if (this.State == CommunicationState.Faulted) 
        {
            this.Abort();
        } 
        else 
        {
            this.Close();
        }
    }
}

这似乎是能够再次让使用块毫无遮拦故障状态异常的危险。

This appears to be able to allow the using block again without the danger of masking a faulted state exception.

那么,还有没有其他陷阱我要寻找出使用这些解决方法?有没有人想出更好的东西?

So, are there any other gotchas I have to look out for using these workarounds? Has anybody come up with anything better?

推荐答案

其实,虽然我的博客(见<一href=\"http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-block-issue/573917#573917\">Luke's回答),我觉得<一个href=\"http://web.archive.org/web/20100703123454/http://old.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx\"相对=nofollow>这是比我IDisposable接口的包装好。典型的code:

Actually, although I blogged (see Luke's answer), I think this is better than my IDisposable wrapper. Typical code:

Service<IOrderService>.Use(orderService=>
{
  orderService.PlaceOrder(request);
}


(每评论编辑)


(edit per comments)

由于使用返回void,以处理返回值的最简单的方法是通过捕获变量:

Since Use returns void, the easiest way to handle return values is via a captured variable:

int newOrderId = 0; // need a value for definite assignment
Service<IOrderService>.Use(orderService=>
  {
    newOrderId = orderService.PlaceOrder(request);
  });
Console.WriteLine(newOrderId); // should be updated

这篇关于什么是WCF客户端`using`阻止问题的最佳解决方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆