2011-06-03 211 views

回答

2

就客戶而言,服務的同步或異步版本是相同的(請參閱下面的示例)。因此,同步/異步決策不會影響互操作性。

public class StackOverflow_6231864_751090 
{ 
    [ServiceContract(Name = "ITest")] 
    public interface ITest 
    { 
     [OperationContract] 
     string Echo(string text); 
     [OperationContract] 
     int Add(int x, int y); 
    } 
    [ServiceContract(Name = "ITest")] 
    public interface ITestAsync 
    { 
     [OperationContract(AsyncPattern = true)] 
     IAsyncResult BeginEcho(string text, AsyncCallback callback, object state); 
     string EndEcho(IAsyncResult ar); 
     [OperationContract(AsyncPattern = true)] 
     IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state); 
     int EndAdd(IAsyncResult ar); 
    } 
    public class Service : ITest 
    { 
     public string Echo(string text) { return text; } 
     public int Add(int x, int y) { return x + y; } 
    } 
    public class ServiceAsync : ITestAsync 
    { 
     string Echo(string text) { return text; } 
     int Add(int x, int y) { return x + y; } 
     public IAsyncResult BeginEcho(string text, AsyncCallback callback, object state) 
     { 
      Func<string, string> func = Echo; 
      return func.BeginInvoke(text, callback, state); 
     } 

     public string EndEcho(IAsyncResult ar) 
     { 
      Func<string, string> func = (Func<string, string>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate; 
      return func.EndInvoke(ar); 
     } 

     public IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state) 
     { 
      Func<int, int, int> func = Add; 
      return func.BeginInvoke(x, y, callback, state); 
     } 

     public int EndAdd(IAsyncResult ar) 
     { 
      Func<int, int, int> func = (Func<int, int, int>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate; 
      return func.EndInvoke(ar); 
     } 
    } 
    public static void Test() 
    { 
     foreach (bool useAsync in new bool[] { false, true }) 
     { 
      Type contractType = useAsync ? typeof(ITestAsync) : typeof(ITest); 
      Type serviceType = useAsync ? typeof(ServiceAsync) : typeof(Service); 
      Console.WriteLine("Using {0} service implementation", useAsync ? "Asynchronous" : "Synchronous"); 
      string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
      ServiceHost host = new ServiceHost(serviceType, new Uri(baseAddress)); 
      host.AddServiceEndpoint(contractType, new BasicHttpBinding(), ""); 
      host.Open(); 
      Console.WriteLine("Host opened"); 

      Console.WriteLine("Using the same client for both services..."); 
      ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress)); 
      ITest proxy = factory.CreateChannel(); 
      Console.WriteLine(proxy.Echo("Hello")); 
      Console.WriteLine(proxy.Add(3, 4)); 

      ((IClientChannel)proxy).Close(); 
      factory.Close(); 

      host.Close(); 

      Console.WriteLine("Done"); 
      Console.WriteLine(); 
     } 
    } 
} 
+0

你在問題和你的用戶ID之後命名了這個類? :) +1,簡潔而有指導性的代碼。我喜歡兩個版本都使用「ITest」的代理。 – shambulator 2011-06-03 20:59:33

+0

我剛剛得到了問題中的「鏈接」值,我不知道用戶標識是在它:) – carlosfigueira 2011-06-03 21:06:21

1

如果通過「使服務異步」,你的意思是使用AsyncPattern,那麼我的理解是,這對客戶端根本沒有影響,只有WCF運行時如何調用服務器上的操作。客戶端(即一個WCF客戶端)和以往一樣,自行選擇是否使用異步調用。

From this MSDN page

要定義執行異步不管它是如何被調用的客戶端應用程序的合同操作X ...

和:

在在這種情況下,異步操作以與同步操作相同的形式顯示在元數據中:它作爲單個操作公開,並帶有請求消息和ac相關的響應消息。客戶端編程模型則有一個選擇。他們可以將此模式表示爲同步操作或異步模式,只要服務被調用時發生請求 - 響應消息交換即可。

1

你的服務不需要做任何「特殊的」......他們仍然表現得一樣。另一方面,客戶必須使用異步模式來使用服務。最簡單的方法是使用「添加服務引用...」。只需選中一個小盒子,上面寫着「生成異步操作」,瞧,你可以讓你的服務的異步調用...

這裏有一個很好的資源:How to: Call WCF Service Operations Asynchronously

儘管負面評論,在最後的例子很好。只需訂閱 <服務名稱>完成事件,然後進行異步調用。調用完成後,您的UI線程將被釋放,並且只要呼叫完成,事件就會發生!小心你的新發現的力量!

public class Foo 
{ 
    private BarServiceClient client; 

    public Foo() 
    { 
     client = new BarServiceClient(); 
     client.DoWorkCompleted += Client_DoWorkCompleted; 
    } 

    private void Client_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e) 
    { 
     //e.Result contains your result. 
    } 

    public void DoBar() 
    { 
     client.DoWorkAsync(); //Called asynchronously, UI thread is free! :) 
    } 
}