Dot-Net

WCF 非同步回調

  • May 12, 2011

我已經在我的程式碼中成功實現了 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'

您需要將服務契約 IMessage 的 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();
   }
}

引用自:https://stackoverflow.com/questions/5979252