使用.net 3.0是一个很好的线程恢复和挂起的替代品

本文关键字:线程 很好 恢复 替代品 挂起 一个 net 使用 | 更新日期: 2023-09-27 17:50:35

我受限于。net 3.0: 这是外部强加的要求。

我需要处理来自泛型队列的字符串。主线程将对字符串进行Enqueue,工作线程将对字符串进行Dequeue,然后处理它们。在工作线程的顶部,它将自己挂起,并在有东西进入队列时等待恢复。然后清空队列(在每个项目退出队列时处理它们),然后在队列为空时挂起自己。

我创建了一个小示例程序,简洁地说明了基本逻辑。我知道enqueuedequeue需要被保护,但它们在这里是原始的,因为这不是我查询的重点。

我看了看使用信号量和互斥对象,但我理解文档的方式,似乎没有一种方法可以在不等待的情况下发出事件信号。我想要的是恢复来解除阻塞工作线程(如果它被阻塞),以便它可以通过队列循环。这个信号只在主线程向队列中添加一个项目时才会发生。如果工作线程已经在工作,那么它将继续工作,直到队列为空。需要这个信号只是为了启动工作线程,如果它被赶上了,正在等待一些事情要做。

using System;
using System.Collections.Generic;
using System.Threading;
namespace QueueProcessor
{
    class Program
    {
        static Queue<string> _Messages = new Queue<string>();
        static bool _Continue = true;
        static Thread _DequeueThread = null;
        static void Main( string[] args )
        {
            _DequeueThread = new Thread( DequeueThread );
            _DequeueThread.Start();
            for(;;)
            {
                Console.WriteLine( "Entersomething here:");
                string something = Console.ReadLine();
                if( something.Equals("quit") )
                {
                    _Continue = false;
                    ResumeThread();
                    break;
                }
                _Messages.Enqueue( something );
                ResumeThread();
            }
        }
        static void ResumeThread( )
        {
            try
            {
                _DequeueThread.Resume();  // .NET 3.0 is the limit
            }
            // If it is already resumed, the frame work throws an exception.
            // This seem unneccesary since if it is already resumed then what's the bother?
            catch( ThreadStateException ) 
            {
                Console.WriteLine( "Thread already running....." );
            }
        }
        static void SuspendThread()
        {
            _DequeueThread.Suspend(); // .NET 3.0 is the limit
        }
        static void DequeueThread()
        {
            Random randomTime = new Random();
            while( _Continue )
            {
                SuspendThread();
                while( _Messages.Count > 0)
                {
                    string message = _Messages.Dequeue();
                    Console.WriteLine( String.Format ( "Dequeue:{0}", message ) );
                    int timeout = randomTime.Next();
                    timeout %= 4000;
                    Thread.Sleep(timeout); // simulated taking a while to process message
                }
            }
        }
    }
}

使用.net 3.0是一个很好的线程恢复和挂起的替代品

这是完整的答案。谢谢Alexi为我指出了正确的方向。

using System;
using System.Collections.Generic;
using System.Threading;
namespace QueueProcessor
{
    class Program
    {
        static Queue<string> _Messages = new Queue<string>();
        static bool _Continue = true;
        static Thread _DequeueThread = null;
        static AutoResetEvent _Latch = null;
        static void Main( string[] args )
        {
            _DequeueThread = new Thread( DequeueThread );
            _Latch = new AutoResetEvent(false);
            _DequeueThread.Start();
            for(;;)
            {
                Console.WriteLine( "Entersomething here:");
                string something = Console.ReadLine();
                if( something.Equals("quit") )
                {
                    _Continue = false;
                    ResumeThread();
                    break;
                }
                lock( _Messages )
                {
                    _Messages.Enqueue( something );
                }
                ResumeThread();
            }
        }
        static void ResumeThread( )
        {
            _Latch.Set();
        }
        static void SuspendThread()
        {
            _Latch.WaitOne();
        }
        static void DequeueThread()
        {
            Random randomTime = new Random();
            while( _Continue )
            {
                SuspendThread();
                string message = string.Empty;
                for(;;)
                {
                    lock ( _Messages )
                    {
                        message = _Messages.Count == 0 ? string.Empty : _Messages.Dequeue();
                    }
                    if( String.IsNullOrEmpty( message ) ) break; // Loop exit condition
                    Console.WriteLine( String.Format ( "Dequeue:{0}", message ) );
                    int timeout = randomTime.Next();
                    timeout %= 4000;
                    Thread.Sleep(timeout); // simulated taking a while to process message
                }
            }
        }
    }
}