通过引用返回一个对象

时间:2010-10-25 13:18:25

标签: c# multithreading pointers reference

我在返回在其他线程中创建的对象时遇到问题。 情况就是这样,我的应用程序需要向远程服务器发送一些请求并等待回答。 在主线程(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);
}

Thread3:

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

除了Message引用之外,整个过程都在工作。 当我读取对象时,我传递了ref键,我有一个空值。

有人可以帮助我吗?

提前致谢。

4 个答案:

答案 0 :(得分:3)

使用ref传递参数时,可以在函数中设置对象引用。当你像这样使用它时:

w.MessageWithAnswer = msgWithAnswer;

它没有使w.MessageWithAnswer成为引用的副本 - 它将w.MessageWithAnswer设置为msgWithAnswer当前所指的任何内容。分配MessageWithAnswer时,它不会更改msgWithAnswer。

答案 1 :(得分:2)

我解决这个问题,添加一个保留对象的类(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();       
} 

这个解决方案对我很有用。

感谢所有帮助我解决这个问题的人。

答案 2 :(得分:1)

您没有给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); 
   } 

答案 3 :(得分:1)

我使用Action个对象而不是引用,因为(如前所述)你不能像你想要的那样使用ref。见下文:

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