C#和#x2B;螺纹+;串行端口+;锁

C#和#x2B;螺纹+;串行端口+;锁,c#,multithreading,serial-port,C#,Multithreading,Serial Port,我必须编写代码,为一个项目创建两个线程。一个线程处理由静态列表访问的信息,该信息由事件处理程序接收,然后该线程必须向串行端口发送一些数据。另一个线程必须等待用户在控制台屏幕上输入数据,然后将数据发送到同一串行端口。如何创建在baackground中运行的第二个线程?如何允许此线程将数据发送到串行端口?如何创建锁,以便在事件处理程序向静态列表添加新信息时后台线程暂停 另一个选项是让主线程处理用户输入和后台线程处理信息。这两种方法都将需要发送到串行端口的数据格式化,并将该数据放入队列中。第三个线程从

我必须编写代码,为一个项目创建两个线程。一个线程处理由静态列表访问的信息,该信息由事件处理程序接收,然后该线程必须向串行端口发送一些数据。另一个线程必须等待用户在控制台屏幕上输入数据,然后将数据发送到同一串行端口。如何创建在baackground中运行的第二个线程?如何允许此线程将数据发送到串行端口?如何创建锁,以便在事件处理程序向静态列表添加新信息时后台线程暂停

另一个选项是让主线程处理用户输入和后台线程处理信息。这两种方法都将需要发送到串行端口的数据格式化,并将该数据放入队列中。第三个线程从队列中删除数据并将其写入串行端口

队列是一种并发数据结构,可以处理多个读写器

这样做的好处是没有显式锁定,因此可以消除一系列潜在的多线程危害。处理线程不会阻止输出,而是将数据放入队列并继续。这允许以全速进行处理

它还可以防止在用户键入某些内容,然后程序必须等待处理器的消息被发送,然后等待他的消息被发送时可能发生的延迟

请注意,如果通过串行端口发送的数据是二进制而不是字符串,则该采集可能是一个
阻塞采集

这会创建一个比您绝对需要的多的线程,但在我看来,这是一个更干净的设计

所以你有:

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);   
}
private BlockingCollection outputQueue=new BlockingCollection();
//处理信息的线程
私有void数据处理器()
{
//初始化
//过程数据
而()
{
字符串foo=CreateOutputFromData();
//把它放在队列上
添加(foo);
}
}
//输出线程
私有void输出线程()
{
//初始化串行端口
//从队列中读取数据,直到结束
字符串文本;
while(outputQueue.TryTake(out text,Timeout.Infinite))
{
//将文本输出到串行端口
}
}
//主线
公用干管()
{
//创建处理线程
var processingThread=Task.Factory.StartNew(()=>DataProcessor(),TaskCreationOptions.LongRunning);
//创建输出线程
var outputThread=Task.Factory.StartNew(()=>outputThread(),TaskCreationOptions.LongRunning);
//等待用户输入和处理
而()
{
var input=Console.ReadLine();
//可能在发送输入之前处理输入
var dataToOutput=ProcessInput(输入);
//把它放在队列上
添加(dataToOutput);
}
//告诉处理线程退出
//完成后,将队列标记为已完成
outputQueue.CompleteAdding();
//等待线程退出。
WaitAll(outputThread,processingThread);
}

另一个选项是让主线程处理用户输入和后台线程处理信息。这两种方法都将需要发送到串行端口的数据格式化,并将该数据放入队列中。第三个线程从队列中删除数据并将其写入串行端口

队列是一种并发数据结构,可以处理多个读写器

这样做的好处是没有显式锁定,因此可以消除一系列潜在的多线程危害。处理线程不会阻止输出,而是将数据放入队列并继续。这允许以全速进行处理

它还可以防止在用户键入某些内容,然后程序必须等待处理器的消息被发送,然后等待他的消息被发送时可能发生的延迟

请注意,如果通过串行端口发送的数据是二进制而不是字符串,则该采集可能是一个
阻塞采集

这会创建一个比您绝对需要的多的线程,但在我看来,这是一个更干净的设计

所以你有:

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);   
}
private BlockingCollection outputQueue=new BlockingCollection();
//处理信息的线程
私有void数据处理器()
{
//初始化
//过程数据
而()
{
字符串foo=CreateOutputFromData();
//把它放在队列上
添加(foo);
}
}
//输出线程
私有void输出线程()
{
//初始化串行端口
//从队列中读取数据,直到结束
字符串文本;
while(outputQueue.TryTake(out text,Timeout.Infinite))
{
//将文本输出到串行端口
}
}
//主线
公用干管()
{
//创建处理线程
var processingThread=Task.Factory.StartNew(()=>DataProcessor(),TaskCreationOptions.LongRunning);
//创建输出线程
var outputThread=Task.Factory.StartNew(()=>outputThread(),TaskCreationOptions.LongRunning);
//等待用户输入和处理
而()
{
var input=Console.ReadLine();
//可能在发送输入之前处理输入
var dataToOutput=ProcessInput(输入);
//把它放在队列上
添加(dataToOutput);
}
//告诉处理线程退出
//完成后,将队列标记为已完成
outputQueue.CompleteAdding();
//等待线程退出。
WaitAll(outputThread,processingThread);
}

另一个选项是让主线程处理用户输入和后台线程处理信息。这两种方法都将需要发送到串行端口的数据格式化,并将该数据放入队列中。第三个线程从队列中删除数据并将其写入串行端口