线程,两个线程之间的通信c#

时间:2012-01-06 20:03:59

标签: c# .net multithreading visual-studio

我想知道在两个线程之间实现通信的最佳方法是什么。我有一个线程生成随机数(类发件人),现在我想要另一个线程(类接收器),它将接收生成的随机数。 这是发件人:

public  class Sender
{
    public int GenerateNumber(){


        //some code
        return randomNumber;
    }
}

在Main函数中,我将启动这些线程:

static void Main(string[] args){

     Sender _sender=new Sender();
     Thread thread1=new Thread(new ThreadStart(_sender.GenerateNumber));

}

感谢您的帮助

5 个答案:

答案 0 :(得分:20)

如果您使用的是.NET 4,我建议使用更高级别的抽象:Task<TResult>。您的第一个线程可以安排任务(可能最终创建一个线程,或者在现有任务处理线程上安排),然后可以检查状态,阻止结果等等。

如果你想做的不仅仅是一次性任务,你可能想要使用生产者/消费者队列 - 再次,.NET 4通过BlockingCollection<T>帮助解决这个问题。

答案 1 :(得分:6)

这是使用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);
    }
}

<小时/> 我只想更新我的答案,提供我认为使用Jon Skeet在他的答案中指出的.NET 4中的Task<TResult>类的上述示例的等效代码。信用证指示他指出。非常感谢,乔恩。我还没有理由使用那门课程,当我看到它的使用方式时,我感到非常惊喜。

除了使用此类后您获得的性能优势之外,使用Task<TResult>类编写等效代码似乎要容易得多。例如,上面Main方法的主体可以重写,如下所示:

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

如果您不需要为任务指定超时并且无限期地等待它完成,那么您可以使用更少的代码来编写它:

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

答案 2 :(得分:2)

您需要在发送方和接收方之间共享某种资源(列表,队列等)。并且您必须同步对此资源的访问权限,否则您将无法在线程之间传递数据。

答案 3 :(得分:0)

如果你所做的只是在一个线程中生成一个随机数,我可能会创建一个线程安全对象来代替它。

lock(syncRoot)
{
    myCurrentRandom = Generate();
    return myCurrentRandom;
}

答案 4 :(得分:0)

实现两个线程之间通信的“最佳”方式实际上取决于需要传达的内容。您的示例似乎是典型的生产者/消费者问题。我会使用同步队列。查看同步集合的MSDN文档。您可以使用Queue.Synchronized方法获取Queue对象的同步包装器。然后,让生产者线程调用Enqueue(),消费者调用Dequeue()。