2010-04-11 2 views
0

Вот код сервера:Duplex Договор GetCallbackChannel всегда возвращает нулевой экземпляр

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.ServiceModel; 
    using System.Runtime.Serialization; 
    using System.ServiceModel.Description; 



    namespace Console_Chat 
{ 


    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMyCallbackContract))] 
    public interface IMyService 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToServer(string msg); 

     [OperationContract(IsOneWay = false)] 
     bool ServerIsResponsible(); 

    } 



    [ServiceContract] 
    public interface IMyCallbackContract 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToClient(string msg); 

     [OperationContract(IsOneWay = true)] 
     void ClientIsResponsible(); 



    } 


    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
    public class MyService : IMyService 
    { 

     public IMyCallbackContract callback = null; 

    /* 
    { 
      get 
      { 
       return OperationContext.Current.GetCallbackChannel<IMyCallbackContract>(); 
      } 
     } 
     */ 

     public MyService() 
     { 
      callback = OperationContext.Current.GetCallbackChannel<IMyCallbackContract>(); 
     } 

     public void NewMessageToServer(string msg) 

     { 
      Console.WriteLine(msg); 
     } 

     public void NewMessageToClient(string msg) 
     { 

      callback.NewMessageToClient(msg); 
     } 


     public bool ServerIsResponsible() 
     { 
      return true; 
     } 

    } 




    class Server 
    { 
     static void Main(string[] args) 
     { 
      String msg = "none"; 


      ServiceMetadataBehavior behavior = new 
      ServiceMetadataBehavior(); 


      ServiceHost serviceHost = new 
      ServiceHost(
      typeof(MyService), 
      new Uri("http://localhost:8080/")); 

      serviceHost.Description.Behaviors.Add(behavior); 

      serviceHost.AddServiceEndpoint(
       typeof(IMetadataExchange), 
       MetadataExchangeBindings.CreateMexHttpBinding(), 
       "mex"); 


      serviceHost.AddServiceEndpoint(
       typeof(IMyService), 
       new WSDualHttpBinding(), 
       "ServiceEndpoint" 
       ); 

      serviceHost.Open(); 
      Console.WriteLine("Server is up and running"); 

      MyService server = new MyService(); 
      server.NewMessageToClient("Hey client!"); 
/* 

      do 
      { 
       msg = Console.ReadLine(); 

       // callback.NewMessageToClient(msg); 


      } while (msg != "ex"); 

    */ 
      Console.ReadLine();  

     } 
    } 
} 

Вот является клиентом:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ServiceModel; 
using System.Runtime.Serialization; 
using System.ServiceModel.Description; 
using Console_Chat_Client.MyHTTPServiceReference; 



namespace Console_Chat_Client 
{ 
    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMyCallbackContract))] 
    public interface IMyService 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToServer(string msg); 

     [OperationContract(IsOneWay = false)] 
     bool ServerIsResponsible(); 

    } 



    [ServiceContract] 
    public interface IMyCallbackContract 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToClient(string msg); 

     [OperationContract(IsOneWay = true)] 
     void ClientIsResponsible(); 

    } 




    public class MyCallback : Console_Chat_Client.MyHTTPServiceReference.IMyServiceCallback 
    { 

     static InstanceContext ctx = new InstanceContext(new MyCallback()); 

     static MyServiceClient client = new MyServiceClient(ctx); 



     public void NewMessageToClient(string msg) 
     { 
      Console.WriteLine(msg); 
     } 

     public void ClientIsResponsible() 
     { 

     } 


       class Client 
       { 
        static void Main(string[] args) 
        { 
         String msg = "none"; 





         client.NewMessageToServer(String.Format("Hello server!")); 


         do 
         { 
          msg = Console.ReadLine(); 
          if (msg != "ex") 
           client.NewMessageToServer(msg); 
          else client.NewMessageToServer(String.Format("Client terminated")); 
         } while (msg != "ex"); 
        } 
       } 






    } 
} 

обратного вызова = OperationContext.Current.GetCallbackChannel(); Эта строка constonly генерирует исключение NullReferenceException, в чем проблема?

Спасибо!

ответ

3

Вы не можете просто запустить службу WCF с помощью договора обратного вызова и немедленно попытаться выполнить обратный вызов клиента. Клиентов пока нет.

В вашем коде я вижу, как вы вручную создаете экземпляр MyService и пытаетесь выполнить метод обратного вызова. Это просто не сработает. Если вы хотите использовать метод GetCallbackChannel, это необходимо сделать, когда на самом деле есть канал - то есть в контексте фактической операции, вызываемой удаленным клиентом WCF. В противном случае, нет тока OperationContext, и вы получите исключение с нулевой ссылкой, потому что OperationContext.Current возвращает null.

Обратные вызовы предназначены для использования при длительных сервисных операциях. Например:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
public class MyService : IMyService 
{ 
    // One-way method 
    public void PerformLongRunningOperation() 
    { 
     var callback = 
      OperationContext.Current.GetCallbackChannel<IMyCallbackContract>(); 
     var result = DoLotsOfWork(); 
     callback.LongRunningOperationFinished(result); 
    } 
} 

Чтобы проверить это, вы бы на самом деле создать клиент - начать новый проект, добавить ссылку на эту услугу, реализовать функцию обратного вызова, который генерирует импортер, создать InstanceContext с обратным вызовом, создать прокси-сервера клиента с использованием этого InstanceContext и, наконец, вызвать его метод PerformLongRunningOperation.

Если вы пытаетесь разработать реализацию pub/sub, где клиенты фактически не инициируют операции, а просто регистрируются для получения обратного вызова, посмотрите эту страницу: Using Callback Contracts in WCF for Asynchronous Publish/Subscribe Event-Style Communication.

+3

deadlink !!!!!!! – David

+0

Ссылка мертва ... –

+0

Начните [здесь] (http://stackoverflow.com/questions/8193518/any-good-wcf-publish-subscribe-framework-tutorials-out-there), возможно. Эта ссылка предлагает несколько сайтов с рабочими ссылками, чтобы узнать больше о pub/sub. – shipr

Смежные вопросы