简体   繁体   English

如何在.NET 2.0 / 3.5中将消息从一个线程异步排队(字符串)到另一个线程?

[英]How to asynchronously queue (string) messages from one thread to another in .NET 2.0/3.5?

I found the article regarding what I want to implement at Queue implementation in C# . 我找到了有关要在C#中的Queue实现中实现的内容的文章。 But the article is based on .Net 4.0. 但是本文基于.Net 4.0。 and MSDN website has very simple example only. 而MSDN网站仅具有非常简单的示例。 so decided to post this here. 因此决定在这里发布。

That is, I'd like to implement that a thread displays a string asynchronously in dos prompt window by taking the string from a queue. 也就是说,我想实现一个线程通过从队列中获取字符串在dos提示窗口中异步显示字符串。 Another thread might add additional strings in the string queue asynchronously as well(string maximum entry is 20, once fill maximum entry, no more addition). 另一个线程也可能异步在字符串队列中添加其他字符串(最大字符串输入为20,一次填充最大条目,不再添加)。 And I'd like to run this application until the queue is empty based on .Net 2.0 or 3.5.(VS2008) 而且我想运行此应用程序,直到基于.Net 2.0或3.5的队列为空。(VS2008)

Queuing implementation looks simple because .Net provides it, but I don't know how to implement asynchronous part with this queue. 排队实现看起来很简单,因为.Net提供了它,但是我不知道如何使用此队列实现异步部分。

Thank you. 谢谢。

So what I gather is you want to use essentially the ConcurrentQueue but you're stuck in .NET 3.5 and cannot use it (because it doesn't exist). 所以我要收集的是,您实际上想使用ConcurrentQueue但是您陷在.NET 3.5中,无法使用它(因为它不存在)。

This goes back to simple operation locking. 回到简单的操作锁定。 You don't want two threads accessing the same object at the same time. 您不希望两个线程同时访问同一对象。

Before You Start : Read This book on C# Threading by Joseph Albahari 开始之前 :阅读Joseph Albahari撰写的有关C#线程的本书

It goes over .NET Threading and even just skimming it will help you prevent running into bad threading mistakes. 它遍历.NET线程,甚至只是略读它也可以帮助您防止遇到严重的线程错误。

There's 2 things you essentially need to do, so let's break this down: 您本质上需要做两件事,所以让我们分解一下:

Accessing the Queue safely 安全地访问队列

You can use the Generic Queue<T> Class to implement your message queue, however all operations that change this object need to be handled safely. 您可以使用Generic Queue<T> Class实现您的消息队列, 但是更改此对象的所有操作都必须安全处理。

The simplest form of doing this is using a Lock Statement . 最简单的形式是使用Lock语句

lock(myQueue)
{
   myQueue.Enqueue(message);
}

You must lock around all operations, so the three you should need are .Enqueue(...) , .Dequeue() and .Count since they all access data. 您必须锁定所有操作,因此您需要的三个是.Enqueue(...) .Dequeue().Count因为它们都访问数据。

This will prevent you from running into multi-threading problems with queueing/dequeuing your messages and life will be good. 这将防止您遇到使消息排队/出队的多线程问题,并且生活会很好。

Waiting for a Message 等待消息

To wait for a message you have a number of ways you can solve this. 要等待消息,您有多种解决方法。 Most of them are outlined in the e-book i linked above. 我上面链接的电子书概述了其中的大多数内容。

The simplest is a Thread.Sleep Loop 最简单的是Thread.Sleep循环

while(appIsRunning)
{
    Thread.Sleep(100);
    lock(myQueue)
    {
        while(myQueue.Count > 0)
        {
           Console.WriteLine(myQueue.Dequeue());
        }
    }
}

Note: This is not the BEST way to do it, just the simplest example 注意:这不是最好的方法,只是最简单的示例

What this does is simply schedules this thread to run again at least 100ms from now. 这样做只是安排此线程从现在起至少100ms再次运行。 (There's no gaurantee it'll run 100ms from now, just not before that time). (没有保证,它将从现在开始运行100毫秒,而不会在该时间之前运行)。 Then it locks the queue so no writes can happen to it, it empties the queue and writes the lines to the screen then loops again. 然后,它锁定队列,因此不会发生任何写操作,它清空队列并将行写入屏幕,然后再次循环。

If the queue is empty it'll just go back to sleeping. 如果队列为空,它将回到睡眠状态。

The other solution is using a Pulse/Wait 另一种解决方案是使用Pulse / Wait

Monitor.Pulse and Monitor.Wait are a ping-pong style thread control paradigm. Monitor.PulseMonitor.Wait是一种乒乓样式的线程控制范例。

You can have your loop in the main thread Monitor.Wait() and when you add a message to the queue you can Monitor.Pulse() to release the lock it's to a waiting thread. 您可以在主线程Monitor.Wait()循环,然后将消息添加到队列中时,可以使用Monitor.Pulse()释放对等待线程的锁定。

This is more semantically relevant but probably less efficient because your context switch is happening on demand for each message. 这在语义上更相关,但可能效率较低,因为您的上下文切换是针对每条消息按需进行的。

There's about 10 other ways to do this, most are outlined in that book but that's essentially the jist of it. 大约有10种其他方法可以完成此操作,大多数方法在该书中都有概述,但这实质上是其精髓。

Please see Event Signaling Section of Joseph's Book for examples of all the signaling methods. 有关所有信令方法的示例,请参见约瑟夫书的事件信令部分

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM