2011-05-12 226 views
6

我已經在我的代碼中成功實現了WCF回調模式,現在我想實現異步回調。這裏是我的界面代碼:WCF異步回調

[ServiceContract(Name = "IMessageCallback")] 
public interface IMessageCallback 
{ 
    [OperationContract(IsOneWay = true)] 
    void OnMessageAdded(string message, DateTime timestamp); 
} 

[ServiceContract(Name="IMessageCallback")] 
public interface IAsyncMessageCallback 
{ 
    [OperationContract(AsyncPattern = true)] 
    IAsyncResult BeginOnMessageAdded(string msg, DateTime timestamp, AsyncCallback callback, object asyncState); 
    void EndOnMessageAdded(IAsyncResult result); 
} 

[ServiceContract(CallbackContract = typeof(IMessageCallback))] 
public interface IMessage 
{ 
    [OperationContract] 
    void AddMessage(string message); 
} 

要使用我聲明我的渠道和終端,像這樣的同步回調:

DuplexChannelFactory<IMessage> dcf = new DuplexChannelFactory<IMessage>(new InstanceContext(this), "WSDualHttpBinding_IMessage"); 
<endpoint address="net.tcp://localhost:8731/Message/" 
      binding="netTcpBinding" 
      contract="WCFCallbacks.IMessage" name="WSDualHttpBinding_IMessage"> 

我有麻煩終端和渠道的正確組合,以利用異步回電話。有人能指引我朝着正確的方向嗎?

此外,當執行下面的代碼行:

OperationContext.Current.GetCallbackChannel<IAsyncMessageCallback>(); 

我收到以下錯誤:

Unable to cast transparent proxy to type 'WCFCallbacks.IAsyncMessageCallback' 

回答

10

您需要服務合同即時聊天的CallbackContract屬性更改該類型(IAsyncMessageCallback)。下面的示例使用異步回調進行運行。

public class StackOverflow_5979252 
{ 
    [ServiceContract(Name = "IMessageCallback")] 
    public interface IAsyncMessageCallback 
    { 
     [OperationContract(AsyncPattern = true)] 
     IAsyncResult BeginOnMessageAdded(string msg, DateTime timestamp, AsyncCallback callback, object asyncState); 
     void EndOnMessageAdded(IAsyncResult result); 
    } 
    [ServiceContract(CallbackContract = typeof(IAsyncMessageCallback))] 
    public interface IMessage 
    { 
     [OperationContract] 
     void AddMessage(string message); 
    } 
    [ServiceBehavior(IncludeExceptionDetailInFaults = true, ConcurrencyMode = ConcurrencyMode.Multiple)] 
    public class Service : IMessage 
    { 
     public void AddMessage(string message) 
     { 
      IAsyncMessageCallback callback = OperationContext.Current.GetCallbackChannel<IAsyncMessageCallback>(); 
      callback.BeginOnMessageAdded(message, DateTime.Now, delegate(IAsyncResult ar) 
      { 
       callback.EndOnMessageAdded(ar); 
      }, null); 
     } 
    } 
    class MyClientCallback : IAsyncMessageCallback 
    { 
     public IAsyncResult BeginOnMessageAdded(string msg, DateTime timestamp, AsyncCallback callback, object asyncState) 
     { 
      Action<string, DateTime> act = (txt, time) => { Console.WriteLine("[{0}] {1}", time, txt); }; 
      return act.BeginInvoke(msg, timestamp, callback, asyncState); 
     } 

     public void EndOnMessageAdded(IAsyncResult result) 
     { 
      Action<string,DateTime> act = (Action<string,DateTime>)((System.Runtime.Remoting.Messaging.AsyncResult)result).AsyncDelegate; 
      act.EndInvoke(result); 
     } 
    } 
    static Binding GetBinding() 
    { 
     return new NetTcpBinding(SecurityMode.None); 
    } 
    public static void Test() 
    { 
     string baseAddress = "net.tcp://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     host.AddServiceEndpoint(typeof(IMessage), GetBinding(), ""); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     InstanceContext instanceContext = new InstanceContext(new MyClientCallback()); 
     DuplexChannelFactory<IMessage> factory = new DuplexChannelFactory<IMessage>(instanceContext, GetBinding(), new EndpointAddress(baseAddress)); 
     IMessage proxy = factory.CreateChannel(); 
     proxy.AddMessage("Hello world"); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     ((IClientChannel)proxy).Close(); 
     factory.Close(); 
     host.Close(); 
    } 
} 
+0

Figueria - 感謝您的迴應,但是當我將我的客戶端放在單獨的線程上並調用AddMessage時,它會在調用BeginInvoke時阻塞。 – user481779 2011-05-12 19:26:37

+0

您是否將併發模式設置爲您的服務中的多個(或可重入)模式?您還可以將[CallbackBehavior]添加到回調類(我發佈的示例中的MyClientCallback),以在客戶端上設置併發模式。嘗試將其設置爲多個,看看你所看到的是否是一個僵局。 – carlosfigueira 2011-05-12 20:24:56

+0

我試過了,沒有成功。讓我更清楚的是,在我的架構中,我有一項服務爲多個客戶提供服務。客戶端調用服務端函數AddMessage,服務可以回調函數OnMessageAdded上的客戶端(希望是異步的)。所以AddMessage在服務端和客戶端的OnMessageAdded上實現。 – user481779 2011-05-12 20:45:40