Возврат объекта по ссылке - PullRequest
0 голосов
/ 25 октября 2010

У меня проблема с возвратом объекта, созданного в другом потоке.Ситуация такова, что мое приложение должно отправить запрос на удаленный сервер и дождаться ответа.В основном потоке (1) у меня есть метод с именем SendAndWait.Этот метод помещает сообщение в очередь сообщений для отправки и ожидает ответа.Другой поток (2) отправляет сообщения в очередь.Третий поток (3) получает сообщения и возвращает в основной поток (1) сообщение с их ответом.

Это мой код.

Тема 1:

void SendAndWait()
{
    AutoResetEvent waitForAnswer = new AutoResetEvent(false);
    int msgReferenceNumber = 1;
    MyMessage msg;

    // Register to wait for answer to the message with the number = msgReferenceNumber
    RegisterToWait(msgNumber, waitForAnswer, ref msg);
    // Send the request to the server, with the reference number.
    SendRequest(msgReferenceNumber);

    // Wait until the server send my answer
    waitForAnswer.WaitOne();

    // Now I have my  answer. BUT I HAVE msg == null
    MessageBox.Show(msg.Text);
}

Тема 2:

public class WhoWait
{
    public int RefNumMsg;
    public AutoResetEvent WaitForAnswer;
    public MyMessage MessageWithAnswer;
}
// In this Dicctionary I save who wait for answers.
private Dictionary<int, WhoWait> Waiting = new Dictionary<WhoWait>();

void RegisterToWait(int msgRefNumber, AutoResetEvent waitForAnswer, ref msgWithAnswer)
{
  WhoWait w = new WhoWait();
  w.RefNumMsg = msgRefNumber;
  w.WaitForAnswer = waitForAnswer;
  w.MessageWithAnswer = msgWithAnswer;

  Waiting.Add(msgRefNumber, w);
}

Тема 3:

void OnRecieve()
{
     // Get data from server
     MyMessage msg = GetMessageData();

     // Search for someone waiting for this answer
     WhoWait w = Wainting[msg.RefNum];

     // Set the response message
     w.MessageWithAnswer = msg;

     // Warn to the main thread. Message with their answer arrive
     w.WaitForAnswer.Set();
}

Все работает, кроме ссылки на Сообщение.Когда я читаю объект, я передаю ему ключ ref, у меня ноль.

Может ли кто-нибудь мне помочь?

Заранее спасибо.

Ответы [ 4 ]

3 голосов
/ 25 октября 2010

Когда вы используете ref для передачи аргумента, это позволяет вам установить ссылку на объект в функции. Когда вы используете это так:

w.MessageWithAnswer = msgWithAnswer;

Он не делает w.MessageWithAnswer копией ссылки - он устанавливает для w.MessageWithAnswer значение, на которое в данный момент ссылается msgWithAnswer Когда вы назначаете MessageWithAnswer, он не изменит msgWithAnswer.

2 голосов
/ 26 октября 2010

Я решаю это, добавляя класс, который хранит объект (класс OneMessageIn).

// This class keep the copy of the message when arrived
public class OneMessageIn
{
    public MyMessage Message
}

void SendAndWait() 
{ 
    AutoResetEvent waitForAnswer = new AutoResetEvent(false); 
    int msgReferenceNumber = 1; 
    OneMenssageIn msgBox = new OneMessageIn(); 

    // Register to wait for answer to the message with the number = msgReferenceNumber 
    RegisterToWait(msgNumber, waitForAnswer, ref msgBox); 
    // Send the request to the server, with the reference number. 
    SendRequest(msgReferenceNumber); 

    // Wait until the server send my answer 
    waitForAnswer.WaitOne(); 

    // Now I have my answer!!!
    MessageBox.Show(msgBox.Message.Text); 
}

public class WhoWait     
{     
    public int RefNumMsg;     
    public AutoResetEvent WaitForAnswer;     
    public OneMessageIn MessageWithAnswer;     
}     
// In this Dicctionary I save who wait for answers.     
private Dictionary<int, WhoWait> Waiting = new Dictionary<WhoWait>();     

// I'm not sure if ref is necesary, but with it works. I don't try without ref.    
void RegisterToWait(int msgRefNumber, AutoResetEvent waitForAnswer, ref OneMessageIn msgBox)    
{    
  WhoWait w = new WhoWait();    
  w.RefNumMsg = msgRefNumber;    
  w.WaitForAnswer = waitForAnswer;    
  w.MessageWithAnswer = msgBox;    

  Waiting.Add(msgRefNumber, w);    
}

void OnRecieve()       
{       
     // Get data from server       
     MyMessage msg = GetMessageData();       

     // Search for someone waiting for this answer       
     WhoWait w = Wainting[msg.RefNum];       

     // Set the response message       
     w.MessageWithAnswer.Message = msg;       

     // Warn to the main thread. Message with their answer arrive       
     w.WaitForAnswer.Set();       
} 

Это решение отлично работает для меня.

Спасибо всем, кто помогает мне с этой проблемой.

1 голос
/ 25 октября 2010

Я бы использовал Action объекты вместо ссылок, потому что (как уже упоминалось) вы не можете использовать ref s, как вы пытаетесь. Смотрите ниже:

void SendAndWait()
{
    AutoResetEvent waitForAnswer = new AutoResetEvent(false);
    int msgReferenceNumber = 1;
    MyMessage msg;

    // Register to wait for answer to the message with the number = msgReferenceNumber
    RegisterToWait(msgNumber, waitForAnswer, receivedMessage => msg = receivedMessage);

    // Send the request to the server, with the reference number.
    SendRequest(msgReferenceNumber);

    // Wait until the server send my answer
    waitForAnswer.WaitOne();

    // Now I have my  answer. BUT I HAVE msg == null
    MessageBox.Show(msg.Text);
}

public class WhoWait
{
    public int RefNumMsg;
    public AutoResetEvent WaitForAnswer;
    public Action<MyMessage> MessageSetter;
}

void RegisterToWait(int msgRefNumber, AutoResetEvent waitForAnswer, Action<MyMessage> msgSetter)
{
  WhoWait w = new WhoWait();
  w.RefNumMsg = msgRefNumber;
  w.WaitForAnswer = waitForAnswer;
  w.MessageSetter = msgSetter;

  Waiting.Add(msgRefNumber, w);
}


void OnRecieve()
{
     // Get data from server
     MyMessage msg = GetMessageData();

     // Search for someone waiting for this answer
     WhoWait w = Wainting[msg.RefNum];

     // Set the response message
     w.MessageSetter(msg);

     // Warn to the main thread. Message with their answer arrive
     w.WaitForAnswer.Set();
}
1 голос
/ 25 октября 2010

Вы не присваиваете msgWithAnswer значение, вы передаете нулевую ссылку, а не присваиваете нулевую ссылку значение.

   void RegisterToWait(int msgRefNumber, AutoResetEvent waitForAnswer, ref msgWithAnswer) 
   { 
      // msgWithAnswer = something here
      WhoWait w = new WhoWait(); 
      w.RefNumMsg = msgRefNumber; 
      w.WaitForAnswer = waitForAnswer; 
      w.MessageWithAnswer = msgWithAnswer; 

      Waiting.Add(msgRefNumber, w); 
   } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...