以下是我的代码结构的高度简化演示:
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static ConcurrentQueue<string> lst = new ConcurrentQueue<string>();
static bool bExit = false;
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
lst.Enqueue("LINE " + i.ToString());
}
Thread threadCurrent = Thread.CurrentThread;
Task.Run(() =>
{
// #1 this block causes the process to exit at about line 556 on my PC
//while (threadCurrent.IsAlive)
//{
// Thread.Sleep(500);
//}
/////
// #2 this block works as expected and exits after line 999 is printed
//while (threadCurrent.IsAlive || lst.Count > 0)
//{
// Thread.Sleep(500);
//}
/////
// #3 this block never exits the process
threadCurrent.Join();
// forced queue flush would go here
/////
bExit = true;
});
Thread threadWorker = new Thread(new ThreadStart(Worker));
threadWorker.SetApartmentState(ApartmentState.STA);
threadWorker.Start();
}
static private void Worker()
{
while (true)
{
string s;
if (lst.TryDequeue(out s))
{
System.Diagnostics.Debug.WriteLine(s);
}
else
{
Thread.Sleep(100);
}
if (bExit)
break;
}
}
}
}
请参阅 Task.Run() 部分中的 3 个块。在调试器中运行它。使用方法 #1,在我的 PC 上,进程大约在中途退出。#2 按预期工作,#3 永远挂起。
这个想法是主线程将消息发布到队列并在工作线程处理它时立即返回。即使主线程已经退出,我也想确保在进程退出之前处理队列中的所有消息。方法 #2 实现了这一点,但我只是不喜欢睡眠,但如果我必须这样做的话,我会忍受它......:)。
方法#1证明主线程确实在退出,不是吗?所以我认为方法 #3 会在没有睡眠的情况下完成同样的事情?但是 .Join 永远不会返回,为什么?
拉莫斯之舞
相关分类