2011-05-12 2 views
6

코드에서 WCF 콜백 패턴을 성공적으로 구현했으며 이제 비동기 콜백을 구현하려고합니다.WCF 비동기 콜백

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>(); 

내가 얻을 : 당신은 그 유형에 서비스 계약 iMessage를의 CallbackContract 속성을 변경하는

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

답변

10

필요 (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

서비스에 동시성 모드를 다중 (또는 재진입)으로 설정하고 있습니까? [CallbackBehavior]를 콜백 클래스 (게시 한 예제의 MyClientCallback)에 추가하여 클라이언트에서 동시성 모드를 설정할 수도 있습니다. 다중으로 설정하여보고있는 것이 교착 상태인지 확인하십시오. – carlosfigueira

+0

나는 어떤 방법으로도 성공하지 못했습니다. 제 아키텍처에서 여러 클라이언트를 지원하는 서비스를 제공한다는 사실을보다 명확히 밝힙니다. 클라이언트는 서비스 측 함수 AddMessage를 호출하고 서비스는 OnMessageAdded 함수에서 클라이언트에 콜백 (비동기식으로) 할 수 있습니다. 따라서 AddMessage는 클라이언트 쪽에서 서비스 측과 OnMessageAdded로 구현됩니다. – user481779