2011-05-12 148 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