C# 将数据从一个线程传递到另一个线程(持续)

C# 将数据从一个线程传递到另一个线程(持续),c#,.net,multithreading,C#,.net,Multithreading,我有两个持续运行的线程: 生产者-每次迭代都会生成值并将其放入int数组中。该数组将传递给使用者线程。生产者将不再使用生成的值 使用者-每次迭代它都从接收到的数组中创建一个字符串,并将结果打印到控制台 生成的数组值有一个顺序。在两个线程中都应该相同 公共类制作人 { 私有int[]m_输出数据; 私有随机m_numberGenerator=null; 私有线程m_runner=null; 私人消费者m_Consumer=null; 公共制片人() { m_outputData=新整数[10];

我有两个持续运行的线程:

  • 生产者-每次迭代都会生成值并将其放入int数组中。该数组将传递给使用者线程。生产者将不再使用生成的值

  • 使用者-每次迭代它都从接收到的数组中创建一个字符串,并将结果打印到控制台

  • 生成的数组值有一个顺序。在两个线程中都应该相同


    公共类制作人
    {
    私有int[]m_输出数据;
    私有随机m_numberGenerator=null;
    私有线程m_runner=null;
    私人消费者m_Consumer=null;
    公共制片人()
    {
    m_outputData=新整数[10];
    m_numberGenerator=新随机数();
    m_runner=新线程(新线程开始(运行));
    m_runner.IsBackground=true;
    m_消费者=新消费者();
    }
    公开作废开始()
    {
    m_consumer.Start();
    m_runner.Start();
    }
    私家车
    {
    while(true)
    {
    对于(int i=0;i
    目前,我使用一个简单的循环逐个复制这些值。此循环由锁保护。我已经深入研究了Array.Copy方法,但是,在使用小数组(函数调用)时,它看起来更昂贵


    在我的线程之间传递阵列(性能方面)的最佳方式是什么?

    更新:使用ConcurrentQueue支持多个使用者

    这是一个非常简单的生产者/消费者示例,使用Task.Run()而不是线程

    这里非常重要的一点是生产者和消费者的实现是完全解耦的。并使用
    ConcurrentQueue
    在生产者和消费者之间共享信息

    private static void Producer(ConcurrentQueue<int[]> eventQueue, CancellationToken cancellationToken)
    {
        Random m_numberGenerator = new Random();
    
        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();
    
            int[] m_outputData = new int[10];
    
            for (int i = 0; i < m_outputData.Length; i++)
            {
                m_outputData[i] = m_numberGenerator.Next(1, 100);
            }
    
            eventQueue.Enqueue(m_outputData);
    
            Thread.Sleep(m_numberGenerator.Next(100, 201));
        }
    }
    
    private static void Consumer(ConcurrentQueue<int[]> eventQueue, CancellationToken cancellationToken)
    {
        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();
    
            int[] m_inputData;
            if (eventQueue.TryDequeue(out m_inputData))
            {
                Console.WriteLine(string.Join(" ", m_inputData));
            }
            else
            {
                Console.WriteLine("No new data is available.");
            }
            Thread.Sleep(100);
        }
    }
    
    static void Main(string[] args)
    {
        ConcurrentQueue<int[]> eventQueue = new ConcurrentQueue<int[]>();
    
        CancellationTokenSource consumerTokenSource = new CancellationTokenSource();
        CancellationToken consumerCancellationToken = consumerTokenSource.Token;
    
        Task.Run(() => Consumer(eventQueue, consumerCancellationToken), consumerCancellationToken);
    
        CancellationTokenSource producerTokenSource = new CancellationTokenSource();
        CancellationToken producerCancellationToken = consumerTokenSource.Token;
    
        Task.Run(() => Producer(eventQueue, producerCancellationToken), producerCancellationToken);
    
        Console.WriteLine("Press any ket to exit.");
    
        Console.ReadLine();
    }
    

    ConcurrentQueue将解除锁定。如果希望线程在收到数据之前阻塞,可以使用BlockingCollection。不过,我不会对大型阵列执行此操作。您还必须复制数组,而不是共享对它的引用。为什么生产者启动消费者?生产者了解其消费者不是一个好的做法。如果它们是同一进程的线程,Program.cs应该同时启动这两个线程,它们应该使用等待句柄等进行同步。正如@Zer0所建议的,通信应该是间接的,使用ConcurrentQueue类型的机制。如果您想继续写入输出,您可以尝试,如果输出不存在,则打印“未更改”或仅打印相同的数组。一个很好的解决方案是使用。这是在C#中制作生产者/消费者的最佳方式之一。它是线程安全的,并提供了大量的配置选项。这是不完整的,因为你发布的代码,我认为,不是你真正拥有的。但是,对于您发布的代码,如果有一个生产者和一个消费者在新数据可用时收到通知,那么它应该可以工作。(不是为了解决问题,而是为了展示另一种方法
    private static void Producer(ConcurrentQueue<int[]> eventQueue, CancellationToken cancellationToken)
    {
        Random m_numberGenerator = new Random();
    
        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();
    
            int[] m_outputData = new int[10];
    
            for (int i = 0; i < m_outputData.Length; i++)
            {
                m_outputData[i] = m_numberGenerator.Next(1, 100);
            }
    
            eventQueue.Enqueue(m_outputData);
    
            Thread.Sleep(m_numberGenerator.Next(100, 201));
        }
    }
    
    private static void Consumer(ConcurrentQueue<int[]> eventQueue, CancellationToken cancellationToken)
    {
        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();
    
            int[] m_inputData;
            if (eventQueue.TryDequeue(out m_inputData))
            {
                Console.WriteLine(string.Join(" ", m_inputData));
            }
            else
            {
                Console.WriteLine("No new data is available.");
            }
            Thread.Sleep(100);
        }
    }
    
    static void Main(string[] args)
    {
        ConcurrentQueue<int[]> eventQueue = new ConcurrentQueue<int[]>();
    
        CancellationTokenSource consumerTokenSource = new CancellationTokenSource();
        CancellationToken consumerCancellationToken = consumerTokenSource.Token;
    
        Task.Run(() => Consumer(eventQueue, consumerCancellationToken), consumerCancellationToken);
    
        CancellationTokenSource producerTokenSource = new CancellationTokenSource();
        CancellationToken producerCancellationToken = consumerTokenSource.Token;
    
        Task.Run(() => Producer(eventQueue, producerCancellationToken), producerCancellationToken);
    
        Console.WriteLine("Press any ket to exit.");
    
        Console.ReadLine();
    }
    
    No new data is available.
    8 57 70 28 78 58 40 79 39 87
    61 5 12 75 21 56 77 15 96 29
    No new data is available.
    33 89 26 11 51 72 28 41 78 84
    No new data is available.
    92 74 80 54 78 24 78 68 46 16
    64 78 84 88 40 60 46 1 41 81
    19 25 80 2 68 7 68 51 98 9
    No new data is available.
    67 13 38 95 66 78 54 36 29 82
    No new data is available.
    53 25 48 26 63 32 68 94 78 43
    89 56 55 73 76 55 71 1 95 18
    20 12 71 51 45 93 68 46 5 52
    No new data is available.
    45 72 56 54 42 44 36 83 5 31
    54 24 82 40 92 2 98 64 29 87
    81 6 37 54 13 87 74 26 32 39
    No new data is available.
    68 11 83 18 22 14 28 64 13 14
    18 58 48 69 5 2 67 48 40 24
    No new data is available.
    89 91 51 18 87 32 48 9 78 98
    92 55 71 57 75 79 85 37 64 74
    No new data is available.
    40 87 79 7 43 82 73 59 84 98
    35 21 92 67 5 27 96 16 4 35
    55 65 93 97 48 26 87 62 4 59
    No new data is available.
    47 51 63 39 81 88 66 36 20 15
    No new data is available.
    55 21 50 65 9 75 59 41 48 71
    98 33 14 14 46 35 47 72 22 95
    No new data is available.
    75 74 42 4 66 45 8 50 67 15
    89 10 72 48 82 17 12 4 62 12