2011-05-12 12 views
6

मैंने अपने कोड में डब्ल्यूसीएफ कॉलबैक पैटर्न सफलतापूर्वक कार्यान्वित किया है और अब मैं एक एसिंक्रोनस कॉलबैक को कार्यान्वित करना चाहता हूं।डब्ल्यूसीएफ एसिंक्रोनस कॉलबैक

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"> 

मैं मुसीबत अतुल्यकालिक उपयोग करने के लिए अंत बिंदु और चैनल का सही संयोजन हो रही हो रहा है:

[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); 
} 

तुल्यकालिक कॉलबैक मैं तो जैसे मेरे चैनल और अंत बिंदु घोषित उपयोग करने के लिए: यहाँ मेरी इंटरफ़ेस कोड है वापस कॉल करें। क्या कोई मुझे सही दिशा दिखा सकता है?

इसके अलावा कोड की निम्न पंक्ति निष्पादित किया जाता है जब:

निम्न त्रुटि
OperationContext.Current.GetCallbackChannel<IAsyncMessageCallback>(); 

मैं हो:

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

उत्तर

10

आप उस प्रकार के सेवा अनुबंध iMessage की CallbackContract संपत्ति को बदलने की जरूरत (IAsyncMessageCallback)। नीचे दिया गया उदाहरण async कॉलबैक के साथ चलता है।

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

फिगेरिया - प्रतिक्रिया के लिए धन्यवाद लेकिन जब मैं अपने ग्राहकों को एक अलग धागे पर डालता हूं और AddMessage को कॉल करता हूं तो इसे BeginInvoke कहा जाता है। – user481779

+0

क्या आप अपनी सेवा पर एकाधिक (या पुनर्वित्त) को समवर्ती मोड सेट कर रहे हैं? आप क्लाइंट पर समवर्ती मोड सेट करने के लिए कॉलबैक क्लास (MyClientCallback में पोस्ट किए गए उदाहरण में) में [CallbackBehavior] भी जोड़ सकते हैं। यह देखने के लिए कि आप जो देख रहे हैं वह एक डेडलॉक है, इसे एकाधिक पर सेट करने का प्रयास करें। – carlosfigueira

+0

मैंने इसे सफलतापूर्वक बिना किसी भी तरह से करने की कोशिश की। मुझे और स्पष्ट होना चाहिए कि मेरे आर्किटेक्चर में मेरे पास कई क्लाइंट की सेवा करने वाली सेवा है। ग्राहक सेवा साइड फ़ंक्शन AddMessage को कॉल करते हैं और सेवा ऑनमेसेज फ़ंक्शन पर क्लाइंट (उम्मीदपूर्वक असीमित रूप से) को कॉलबैक कर सकती है। तो AddMessage को क्लाइंट साइड पर सेवा-पक्ष और OnMessage में लागू किया गया है। – user481779

संबंधित मुद्दे