c# - 将数据从一个线程传递到另一个线程(不断地)
问题描述
我有两个不断运行的线程:
Producer - 每次迭代它都会生成值并将它们放入一个 int 数组中。该数组被传递给消费者线程。Producer 不会再次使用生成的值。
消费者 - 每次迭代它都会从接收到的数组中创建一个字符串并将结果打印到控制台。
生成的数组值有一个顺序。它在两个线程中应该是相同的。
public class Producer
{
private int[] m_outputData;
private Random m_numberGenerator = null;
private Thread m_runner = null;
private Consumer m_consumer = null;
public Producer()
{
m_outputData = new int[10];
m_numberGenerator = new Random();
m_runner = new Thread(new ThreadStart(Run));
m_runner.IsBackground = true;
m_consumer = new Consumer();
}
public void Start()
{
m_consumer.Start();
m_runner.Start();
}
private void Run()
{
while (true)
{
for (int i = 0; i < m_outputData.Length; i++)
{
m_outputData[i] = m_numberGenerator.Next(1, 100);
}
m_consumer.SetData(m_outputData);
Thread.Sleep(100);
}
}
}
public class Consumer
{
private int[] m_inputData;
private Thread m_runner = null;
private readonly object m_dataLock = new object();
public Consumer()
{
m_inputData = new int[10];
m_runner = new Thread(new ThreadStart(Run));
m_runner.IsBackground = true;
}
public void Start()
{
m_runner.Start();
}
public void SetData(int[] arr)
{
lock (m_dataLock)
{
for (int i = 0; i < m_inputData.Length; i++)
{
m_inputData[i] = arr[i];
}
}
}
private void Run()
{
while (true)
{
string data = "";
lock (m_dataLock)
{
for (int i = 0; i < m_inputData.Length; i++)
{
data += m_inputData[i].ToString();
data += ",";
}
}
Console.WriteLine(data);
Thread.Sleep(100);
}
}
}
目前,我使用一个简单的循环来一一复制这些值。该循环由锁保护。我已经锁定了 Array.Copy 方法,但是,它在使用小数组(函数调用)时看起来更昂贵。
在我的线程之间传递数组(性能方面)的最佳方式是什么?
解决方案
更新:使用 ConcurrentQueue 支持多个消费者
这是一个使用 Task.Run() 而不是线程的非常简单的生产者/消费者示例。
这里非常重要的一点是生产者和消费者的实现是完全解耦的。并使用 aConcurrentQueue
在生产者和消费者之间共享信息。
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
推荐阅读
- r - 计算 R 矩阵中每列特定整数的数量
- python-3.x - 通知设备应用程序进行设备孪生更新(python)
- javascript - 反应:改变状态 onMouseOver
- vba - 从查询中提取多个电子邮件地址以自动访问电子邮件?
- python - 用 LightGBM 制作 CART / RF 的超参数
- python - Django - Receiving error "too many values to unpack (expected 2)"
- javascript - 如何在可重用的 NPM 包中导出多个 React 组件,以便它们可以独立导入并从应用程序包中排除依赖项?
- java - 如何获得在小米(MIUI)设备中删除联系人的权限?
- excel - 目录中不存在文件时的 VBA 错误处理
- react-native - 如何在本机反应中将图像从本地文件保存到文档目录?