我有一个c#控制台应用程序,它有一些线程可以完成一些工作(下载文件)。 每个线程可以随时在应用程序的任何位置退出应用程序,但我会在控制台上显示正确的消息。跟踪它们是可能的,但对我来说没有意义。我只想检查线程计数或类似的东西,找出哪一个是最后一个线程,并在退出时做一些事情。 这样做的最佳做法是什么?
伪代码:
if (lastThread)
{
cleanUp();
Console.ReadLine();
}
由于
答案 0 :(得分:11)
这是一个使用新的任务并行库可以让生活更轻松的地方。您可以使用多个任务来代替创建线程和在线程上进行旋转处理:
var task1 = Task.Factory.StartNew( () => DoTaskOneWork() );
var task2 = Task.Factory.StartNew( () => DoTaskTwoWork() );
var task3 = Task.Factory.StartNew( () => DoTaskThreeWork() );
// Block until all tasks are done
Task.WaitAll(new[] {task1, task2, task3} );
cleanUp(); // Do your cleanup
如果“任务”只是下载了一堆单独的文件,你甚至可以使用PLINQ使这更简单:
var fileUrls = GetListOfUrlsToDownload();
fileUrls.AsParallel().ForAll( fileUrl => DownloadAndProcessFile(fileUrl) );
cleanUp(); // Do your cleanup
答案 1 :(得分:2)
您丢失线程跟踪的设计并不理想。
根据您产生它们的方式,应该可以通过关联一些每线程可签名对象,然后WaitAll关联那些可签名对象来跟踪每个对象的状态。
每个可签名对象反过来应该在其线程退出时发出信号。当他们都发出信号时,你知道线程都已经死了,你关闭了。您必须确保线程中的异常情况不会导致该线程的相关可签名对象保持未设置状态,否则您的WaitAll
将永远不会返回。这通常意味着例外 - 可以使用try...finally
来确保对象发出信号。
您的新伪代码是
foreach (workitem in list of work)
start up thread associated with a ManualResetEvent or similar
WaitAll for all events to be signalled
cleanup
答案 2 :(得分:1)
你的主线程应该join包含所有工作线程并在它们运行时阻塞。然后,当所有线程都完成时,它会执行清理代码,然后退出。
或者,您可以使用WaitHandle,例如每个帖子ManualResetEvent和wait for all来发信号。