«Исключение System.NullReferenceException было обработано» в объекте WCF - PullRequest
1 голос
/ 11 апреля 2011

Все еще борется с серверной частью моего приложения wcf.

Проблема в том, что создание объекта «обратного вызова» в классе сервера вызвало ошибку «System.NullReferenceException is unhandled».

Если я правильно понимаю, это происходит, когда я создаю этот объект сервера - ServerClass myServer = new ServerClass ();

Так что, я думаю, мне нужно каким-то образом создать список для объектов сервера и автоматически создавать и добавлять эти объекты всякий раз, когда клиент устанавливает соединение. Пожалуйста, предложите, что было бы лучшим способом сделать это?

Вот мой код:

namespace server2
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
            myServer.eventHappened += new EventHandler(eventFunction);
        }

        ServerClass myServer = new ServerClass();
        // here I instance a new server object.
        // yet I believe that I need to make a list, that would store this objects, so that multiple clients would be able to connect,
        // and I would be able to pick, to whom I want to send a callback.

        void eventFunction(object sender, EventArgs e)
        {
            label1.Text = myServer.clientName;
        }

        private ServiceHost duplex;

        private void Form2_Load(object sender, EventArgs e)     /// once the form loads, create and open a new ServiceEndpoint.
        {
            duplex = new ServiceHost(typeof(ServerClass));
            duplex.AddServiceEndpoint(typeof(IfaceClient2Server), new NetTcpBinding(), "net.tcp://localhost:9080/service");
            duplex.Open();
            this.Text = "SERVER *on-line*";
        }

    }




    class ServerClass : IfaceClient2Server
    {

        public event EventHandler eventHappened;

        IfaceServer2Client callback = OperationContext.Current.GetCallbackChannel<IfaceServer2Client>();
        // ERROR: System.NullReferenceException was unhandled

        public string clientName = "noname";

        public void StartConnection(string name)
        {
            clientName = name;
            MessageBox.Show(clientName + " has connected!");

            eventHappened(this, new EventArgs());
            // ERROR: System.NullReferenceException was unhandled :(

            callback.Message_Server2Client("Welcome, " + clientName);
        }

        public void Message_Cleint2Server(string msg)
        {
        }

        public void Message2Client(string msg)
        {
        }

    }




    [ServiceContract(Namespace = "server", CallbackContract = typeof(IfaceServer2Client), SessionMode = SessionMode.Required)]


    public interface IfaceClient2Server           ///// what comes from the client to the server.
    {
        [OperationContract(IsOneWay = true)]
        void StartConnection(string clientName);

        [OperationContract(IsOneWay = true)]
        void Message_Cleint2Server(string msg);
    }


    public interface IfaceServer2Client          ///// what goes from the sertver, to the client.
    {
        [OperationContract(IsOneWay = true)]
        void AcceptConnection();

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

        [OperationContract(IsOneWay = true)]
        void Message_Server2Client(string msg);
    }

}

Спасибо!

Ответы [ 2 ]

2 голосов
/ 11 апреля 2011

Это не может быть сделано таким образом. Прежде всего, канал обратного вызова доступен только внутри операции, а не при создании экземпляра класса обслуживания.

Во-вторых, экземпляры вашего ServerClass создаются хостом службы WCF в зависимости от конфигурации WCF. Например, может быть один экземпляр на вызов (!). Таким образом, создание экземпляра самостоятельно и присоединение обработчика событий не влияет на автоматически созданные экземпляры. Вот почему вы получаете исключение в StartConnection.

Что бы я сделал в этом случае:

  1. Создать одноэлементный класс, который публикует желаемое событие
  2. Прикрепите обработчик к событию из своего основного кода. Это будет код, который слушает события
  3. Создать открытый метод (например, ConnectionStarted), который вызывает событие
  4. Вызовите этот метод из вашего ServerClass

Если вам не нужно ждать завершения обработчика события, вы также можете вызвать событие асинхронно в отдельном потоке. Затем необходимо убедиться, что обработчик событий, присоединенный на шаге 2), правильно обрабатывает контексты потоков, используя, например, this.Invoke (формы) или this.Dispatcher.BeginInvoke (WPF).

0 голосов
/ 11 апреля 2011

Попробуйте поместить эту строку в конструктор класса:

class ServerClass : IfaceClient2Server
{
   public event EventHandler eventHappened;
   IfaceServer2Client callback;

   public ServerClass ()
   {
      callback = OperationContext.Current.GetCallbackChannel<IfaceServer2Client>();
   }

   ...
}

Если вам все еще не повезло, это, вероятно, означает, что вы можете использовать OperationContext.Current только внутри некоторой операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...