我必须编写为项目创建两个线程的代码。一个线程处理由静态列表访问的信息,该信息由事件处理程序接收,然后线程必须将一些数据发送到串行端口。另一个线程必须等待用户在控制台屏幕上输入数据,然后将数据发送到同一串行端口。如何在baackground中创建第二个线程?如何允许此线程将数据发送到串行端口?如何在事件处理程序向静态列表添加新信息时创建锁以使后台线程暂停?
答案 0 :(得分:3)
另一个选择是让主线程处理用户输入和后台线程处理信息。这两种格式都需要将数据格式化到串行端口并将数据放入队列中。第三个线程从队列中删除数据并将其写入串行端口。
队列是一个BlockingCollection<string>,一个可以处理多个读者和编写者的并发数据结构。
这样做的好处是你没有明确的锁定,所以你消除了一堆潜在的多线程危险。处理线程不会阻塞输出,而只是将数据放入队列并继续。这允许处理全速发生。
它还可以防止用户输入内容时发生的潜在延迟,然后程序必须等待处理器的消息发送,然后才能发送消息。
请注意,如果您通过串行端口发送的数据是二进制而不是字符串,则集合可能是BlockingCollection<byte[]>
。
这创建了一个比你绝对需要更多的线程,但在我看来,这是一个更清洁的设计。
所以你有:
private BlockingCollection<string> outputQueue = new BlockingCollection<string>();
// the thread that processes information
private void DataProcessor()
{
// initialization
// process data
while ()
{
string foo = CreateOutputFromData();
// put it on the queue
outputQueue.Add(foo);
}
}
// the output thread
private void OutputThread()
{
// initialize serial port
// read data from queue until end
string text;
while (outputQueue.TryTake(out text, Timeout.Infinite))
{
// output text to serial port
}
}
// main thread
public Main()
{
// create the processing thread
var processingThread = Task.Factory.StartNew(() => DataProcessor(), TaskCreationOptions.LongRunning);
// create the output thread
var outputThread = Task.Factory.StartNew(() => OutputThread(), TaskCreationOptions.LongRunning);
// wait for user input and process
while ()
{
var input = Console.ReadLine();
// potentially process input before sending it out
var dataToOutput = ProcessInput(input);
// put it on the queue
outputQueue.Add(dataToOutput);
}
// tell processing thread to exit
// when you're all done, mark the queue as finished
outputQueue.CompleteAdding();
// wait for the threads to exit.
Task.WaitAll(outputThread, processingThread);
}