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

Posted

技术标签:

【中文标题】如何在 .NET 2.0/3.5 中将(字符串)消息从一个线程异步排队到另一个线程?【英文标题】:How to asynchronously queue (string) messages from one thread to another in .NET 2.0/3.5? 【发布时间】:2012-04-08 10:53:45 【问题描述】:

我在Queue implementation in C# 找到了关于我想要实现的文章。但是这篇文章是基于.Net 4.0的。而 MSDN 网站只有非常简单的例子。所以决定在这里发布。

也就是说,我想通过从队列中获取字符串来实现线程在dos提示窗口中异步显示字符串。另一个线程也可能在字符串队列中异步添加额外的字符串(字符串最大条目为 20,一旦填充最大条目,不再添加)。我想根据.Net 2.0或3.5运行这个应用程序直到队列为空。(VS2008)

队列实现看起来很简单,因为.Net提供了它,但我不知道如何用这个队列实现异步部分。

谢谢。

【问题讨论】:

您可能会发现这个问题的公认答案很有趣:***.com/questions/530211/… 基于你在完成通知时所做的“异步”没有多大意义,而在非阻塞中的“异步”可能不值得复杂,所以即使阿伦的回答没有不完全按照您的要求去做,这可能是正确的方法。 【参考方案1】:

所以我收集到的是,您基本上想使用 ConcurrentQueue,但您被困在 .NET 3.5 中并且无法使用它(因为它不存在)。

这又回到了简单的操作锁定。您不希望两个线程同时访问同一个对象。

开始之前:阅读This book on C# Threading by Joseph Albahari

它涵盖了 .NET 线程,即使只是略读它也会帮助您防止遇到错误的线程错误。

您基本上需要做两件事,所以让我们分解一下:

安全访问队列

您可以使用Generic Queue<T> Class 来实现您的消息队列,但是所有更改此对象的操作都需要安全处理。

执行此操作的最简单形式是使用Lock Statement。

lock(myQueue)

   myQueue.Enqueue(message);

您必须锁定所有操作,因此您需要的三个操作是 .Enqueue(...).Dequeue().Count,因为它们都访问数据。

这将防止您在将消息排队/出队时遇到多线程问题,并且生活会很好。

等待消息

要等待消息,您有多种方法可以解决此问题。其中大部分都在我上面链接的电子书中进行了概述。

最简单的是Thread.Sleep循环

while(appIsRunning)

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

注意:这不是最好的方法,只是最简单的例子

这只是简单地安排这个线程在至少 100 毫秒后再次运行。 (没有保证它会从现在开始运行 100 毫秒,只是在那之前不会运行)。然后它锁定队列,因此不会发生写入,它清空队列并将行写入屏幕,然后再次循环。

如果队列是空的,它就会回到睡眠状态。

另一种解决方案是使用脉冲/等待

Monitor.PulseMonitor.Wait 是一种乒乓式线程控制范例。

您可以在主线程Monitor.Wait() 中设置循环,当您将消息添加到队列时,您可以Monitor.Pulse() 将锁释放到等待线程。

这在语义上更相关,但可能效率较低,因为您的上下文切换是根据每条消息的需要进行的。

还有大约 10 种其他方法可以做到这一点,大部分都在那本书中进行了概述,但这基本上就是它的要点。

请参阅Event Signaling Section of Joseph's Book 了解所有信令方法的示例。

【讨论】:

以上是关于如何在 .NET 2.0/3.5 中将(字符串)消息从一个线程异步排队到另一个线程?的主要内容,如果未能解决你的问题,请参考以下文章

线程可以作为另一个用户执行吗? (.NET 2.0/3.5)

如何在 .NET Core 中将 JSON 序列化为没有转义字符的字符串?

如何在 .NET 中将十六进制“字符串”转换为实际的十六进制值? [复制]

如何在 .Net / C# 中将日期转换为 HTTP 格式的日期

如何在 MVC .ASP NET 中将变量从字符串转换为 int [重复]

如何在 .Net 7 中将 Query 绑定到数组