I'm wondering what is the best way to implement communication between two threads. I have one thread that generates random number(class Sender) and now I want to have another thread(class Receiver) that 'll receive generated random number. This is Sender:
public  class Sender
{
    public int GenerateNumber(){
        //some code
        return randomNumber;
    }
}
Afcourse in Main function I'll start those threads:
static void Main(string[] args){
     Sender _sender=new Sender();
     Thread thread1=new Thread(new ThreadStart(_sender.GenerateNumber));
}
I appreciate your help
Here's a possible approach using a WaitHandle:
class Program
{
    static void Main(string[] args)
    {
        Sender _sender = new Sender();
        Receiver _receiver = new Receiver();
        using (ManualResetEvent waitHandle = new ManualResetEvent(false))
        {
            // have to initialize this variable, otherwise the compiler complains when it is used later
            int randomNumber = 0;
            Thread thread1 = new Thread(new ThreadStart(() =>
            {
                randomNumber = _sender.GenerateNumber();
                try
                {
                    // now that we have the random number, signal the wait handle
                    waitHandle.Set();
                }
                catch (ObjectDisposedException)
                {
                    // this exception will be thrown if the timeout elapses on the call to waitHandle.WaitOne
                }
            }));
            // begin receiving the random number
            thread1.Start();
            // wait for the random number
            if (waitHandle.WaitOne(/*optionally pass in a timeout value*/))
            {
                _receiver.TakeRandomNumber(randomNumber);
            }
            else
            {
                // signal was never received
                // Note, this code will only execute if a timeout value is specified
                System.Console.WriteLine("Timeout");
            }
        }
    }
}
public class Sender
{
    public int GenerateNumber()
    {
        Thread.Sleep(2000);
        // http://xkcd.com/221/
        int randomNumber = 4; // chosen by fair dice role
        return randomNumber;
    }
}
public class Receiver
{
    public void TakeRandomNumber(int randomNumber)
    {
        // do something
        System.Console.WriteLine("Received random number: {0}", randomNumber);
    }
}
Task<TResult> class in .NET 4 pointed out by Jon Skeet in his answer.  Credit goes to him for pointing it out.  Thanks a lot, Jon.  I haven't had a reason to use that class yet, and was pleasantly surprised when I saw how easy it was to use.
Aside from performance benefits that you gain under the hood from using this class, writing equivalent code using the Task<TResult> class seems to be much easier.  For instance, body of the Main method above could be rewritten as shown below:
        Sender _sender = new Sender();
        Receiver _receiver = new Receiver();
        Task<int> getRandomNumber = Task.Factory.StartNew<int>(_sender.GenerateNumber);
        // begin receiving the random number
        getRandomNumber.Start();
        // ... perform other tasks
        // wait for up to 5 seconds for the getRandomNumber task to complete
        if (getRandomNumber.Wait(5000))
        {
            _receiver.TakeRandomNumber(getRandomNumber.Result);
        }
        else
        {
            // the getRandomNumber task did not complete within the specified timeout
            System.Console.WriteLine("Timeout");
        }
If you have no need to specify a timeout for the task and are content to wait indefinitely for it to finish, then you can write this using even less code:
        Sender _sender = new Sender();
        Receiver _receiver = new Receiver();
        Task<int> getRandomNumber = Task.Factory.StartNew<int>(_sender.GenerateNumber);
        // begin receiving the random number
        getRandomNumber.Start();
        // ... perform other tasks
        // accessing the Result property implicitly waits for the task to complete
        _receiver.TakeRandomNumber(getRandomNumber.Result);
                        The "best" way to implement communication between two threads really depends on what needs to be communicated. Your example seems to be a classic producer/consumer problem. I would use a Synchronized Queue. Check out the MSDN documentation for Synchronized Collections. You can use the Queue.Synchronized method to get a synchronized wrapper for a Queue object. Then, have the producer thread call Enqueue() and the consumer call Dequeue().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With