Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程,两个线程之间的通信#_C#_.net_Multithreading_Visual Studio - Fatal编程技术网

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

C# 线程,两个线程之间的通信#,c#,.net,multithreading,visual-studio,C#,.net,Multithreading,Visual Studio,我想知道在两个线程之间实现通信的最佳方式是什么。我有一个线程生成随机数(类发送方),现在我想有另一个线程(类接收方)接收生成的随机数。 这是发件人: public class Sender { public int GenerateNumber(){ //some code return randomNumber; } } 当然,在Main函数中,我将启动这些线程: static void Main(string[] args){

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

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

}

非常感谢您的帮助

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

如果您使用的是.NET4,我建议您使用更高级别的抽象:。您的第一个线程可以安排任务(可能最终创建一个线程,或者安排在现有的任务处理线程上),然后可以根据需要检查状态、阻塞结果等


如果您想执行多个一次性任务,您可能需要使用生产者/消费者队列-同样,.NET 4通过来提供帮助。

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

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

下面是一种使用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中的
任务
类更新我的答案,为上面的例子提供我认为等价的代码。他指出这一点值得赞扬。非常感谢,乔恩。我还没有理由使用这个类,当我看到它是多么容易使用时,我感到惊喜

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

        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\u Sender=new Sender();
接收器_接收器=新接收器();
Task getRandomNumber=Task.Factory.StartNew(_sender.GenerateNumber);
//开始接收随机数
getRandomNumber.Start();
// ... 执行其他任务
//最多等待5秒钟,getRandomNumber任务才能完成
如果(getRandomNumber.Wait(5000))
{
_receiver.TakeRandomNumber(getRandomNumber.Result);
}
其他的
{
//getRandomNumber任务未在指定的超时内完成
System.Console.WriteLine(“超时”);
}
如果不需要为任务指定超时,并且满足于无限期地等待任务完成,则可以使用更少的代码编写此任务:

        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);
Sender\u Sender=new Sender();
接收器_接收器=新接收器();
Task getRandomNumber=Task.Factory.StartNew(_sender.GenerateNumber);
//开始接收随机数
getRandomNumber.Start();
// ... 执行其他任务
//隐式访问Result属性将等待任务完成
_receiver.TakeRandomNumber(getRandomNumber.Result);

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

这两个线程是否同时启动?接收方在等待发送方时在做什么?发送器在生成一个随机数后做什么?在主函数中,我将启动两个线程,线程发送器将工作,然后睡眠3秒钟。此外,我将启动线程接收器实例,该实例将接收数据…基本上线程将在UI用户按esc键之前工作…接收器将写入接收到的控制台编号。是的,这是.net4 thx:)让我帮助您:
int randomNumber=4;//由公平掷骰子选择。
好的一点,但这只是我试图实现的基本方法,只是为了能够在线程之间进行通信,线程发送器将有更复杂的方法:)好的一点,这只是我正在测试的一个函数,以使事情正常工作,之后,发送线程的人将没有更多methods@AintMeBabe-如果您使用的是.NET 4,那么我建议您查看Jon Skeet的答案。看起来你可以使用
任务
类用更少的代码做同样的事情。我知道我必须深入阅读C#depth,所以我今天晚上就开始:)@aintmebab:老实说,C#depth几乎没有触及新的
任务
内容。。。通过MSDN博客文章对任务并行库进行研究可能比这本书更直接。当然,这并不是说我会长期阻止你:)如果我们不能控制制片人怎么办;在我的上下文中,线程A(在我的控制下)做了一些事情,它需要等待线程B引发事件;线程B由库生成。我在听这件事。事件侦听器(在线程B中运行)应该如何通知线程A?我想不出什么,只有一件事。在.NET4中有更好的方法吗?@Jimmy:我建议你用一个新的方法问一个新问题。