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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8763761/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 04:19:53  来源:igfitidea点击:

Threading, communication between two threads c#

c#.netmultithreadingvisual-studio

提问by Avicena00

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:

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

public  class Sender
{
    public int GenerateNumber(){


        //some code
        return randomNumber;
    }
}

Afcourse in Main function I'll start those threads:

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

static void Main(string[] args){

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

}

I appreciate your help

我感谢您的帮助

回答by Mithrandir

You will need some kind of resource (list, queue, etc.) shared between sender and receiver. And you will have to synchronize the access to this resource, otherwise you will not be able to pass data between the threads.

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

回答by Jon Skeet

If you're using .NET 4, I would suggest using a higher level abstraction: Task<TResult>. Your first thread can schedule the task (which may end up creating a thread, or be scheduled on an existing task-handling thread) and can then check for status, block for the result etc as it sees fit.

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

If you want to do more than a one-shot task, you may want to use a producer/consumer queue - again, .NET 4 helps with that via BlockingCollection<T>.

如果您想做的不仅仅是一次性任务,您可能需要使用生产者/消费者队列 - 同样,.NET 4 通过BlockingCollection<T>.

回答by Cole W

If all you are doing is generating a random number in the one thread I would probably create a thread safe object that does this instead.

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

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

回答by Dr. Wily's Apprentice

Here's a possible approach using a WaitHandle:

这是使用 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>Task<TResult>Jon Skeet 在他的答案中指出的 .NET 4 中的类提供我认为是上述示例的等效代码。值得称赞的是他指出了这一点。非常感谢,乔恩。我还没有理由使用那个类,当我看到它是多么容易使用时,我感到很惊喜。

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:

除了使用此类获得的性能优势外,使用该类编写等效代码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");
        }

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

回答by AngCaruso

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().

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