2014-02-05 152 views
2

我有我用来调用异步方法,像这样一个WCF客户端代理:如何关闭客户端代理与异步调用WCF

var prox = new DoSomethingServiceClient("BasicHttpBinding_IDoSomethingService"); 
prox.DoSomethingCompleted += new EventHandler<AsyncCompletedEventArgs>(svcref_DoSomethingCompleted); 
prox.DoSomethingAsync(0, Guid.NewGuid()); 

我什么时候关闭/中止代理?

我在svcref_DoSomethingCompleted的第一行使用sender对象吗?

我在MS文档中看到他们在主线程中关闭代理,而不是在回调中。这是不错的做法吗?看来我错了:

http://msdn.microsoft.com/en-us/library/ms730059(v=vs.110).aspx

我也发现了这一点,使用基于任务的异步这表明你关闭代理在委托的回调,这是我最好样的期待:

http://fun-with-blackhawk.blogspot.com/2010/03/wcf-exception-handling-in-asynchronous.html

+1

我猜的样本工程,因为有一个堵'到Console.ReadLine()''之前客户端.Close()'。如果它不在那里,它可能会在通话完成之前关闭客户端。 –

回答

1

这是WCF变得棘手的地方。当服务器调用回调方法时,它需要在客户端代理关闭之前完成该调用。这意味着完整的往返于客户和回程。 Microsoft示例请求客户端的用户输入(通过Console.ReadLine())触发关闭。如果您想使用异步回调触发关闭,则需要具备创意。例如,您可以在新线程上排队关闭,然后延迟执行。这将允许回调完成其返回到服务器的行程,然后关闭该通道。

添加这样的事情在你的回调:

var currentChannel = OperationContext.Current.Channel; 
ThreadPool.QueueUserWorkItem(o => CloseChannel(currentChannel)); 

,然后这对CloseChannel:

private static void CloseChannel<T>(T channel) 
{ 
    var clientChannel = (IClientChannel)channel; 
    var success = false; 
    try 
    { 
     //sleep before close so the main thread has a chance to catch up 
     Thread.Sleep(10000); 
     clientChannel.Close(); 
     success = true; 
    } 
    catch (CommunicationException ce) 
    { 
     clientChannel.Abort(); 
    } 
    catch (TimeoutException te) 
    { 
     clientChannel.Abort(); 
    } 
    finally 
    { 
     if (!success) 
      clientChannel.Abort(); 
    } 
}