WCF异步回调

use*_*779 7 .net wcf asynchronous callback

我已经在我的代码中成功实现了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);
}
Run Code Online (Sandbox Code Playgroud)

要使用同步回调,我声明了我的通道和端点,如下所示:

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">
Run Code Online (Sandbox Code Playgroud)

我无法获得端点和通道的正确组合以利用异步回调.有人能指出我正确的方向吗?

此外,当执行以下代码行时:

OperationContext.Current.GetCallbackChannel<IAsyncMessageCallback>();
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Unable to cast transparent proxy to type 'WCFCallbacks.IAsyncMessageCallback'
Run Code Online (Sandbox Code Playgroud)

car*_*ira 11

您需要将服务协定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();
    }
}
Run Code Online (Sandbox Code Playgroud)