2014-02-05 151 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(); 
    } 
}