检查ThreadPool线程何时完成的正确方法? [英] Correct way of checking when ThreadPool threads are done?
问题描述
我正在寻找一种检查线程池中所有线程何时完成其任务的方法.当前,我正在使用一个计数器,该计数器在线程完成其工作时以及在counter == 0
调用我的WorkComplete
方法时递减.这似乎可行,但是当我进入最后的工作"时,似乎无法处理结果了吗?或至少UI没有得到它.这是我目前拥有的:
I'm looking for a way of checking when all threads in threadpool have finished their tasks. Currently I'm using a counter that decrements when a thread has finished it's job and when counter == 0
I'm invoking my WorkComplete
method. This seems to work but when i get to the final 'job' it doesn't appear to process the result? Or at least the UI doesn't get it. Here is what i currently have:
排队工作项目+递增计数器
Queuing work items + incrementing counter
foreach (string s in URLs)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), s);
Interlocked.Increment(ref counter);
}
工作:
public void DoWork(object sender)
{
lock (_threadLock)
{
try
{
string url = (string)sender;
result.URL = url;
if (chkFb.Checked)
{
result.Shares = grabber.GetFacebookShares(url);
}
if (chkTwitt.Checked)
{
result.Tweets = grabber.GetTweetCount(url);
}
if (chkPlusOne.Checked)
{
result.PlusOnes = grabber.GetPlusOnes(url);
}
Interlocked.Decrement(ref counter);
this.Invoke(new ThreadDone(ReportProgress), result);
}
catch (Exception exc)
{
MessageBox.Show(string.Format("Errror: {0}", exc.Message);
}
finally
{
if (counter == 0)
{
this.Invoke(new ThreadDone(ReportProgress), result);
this.Invoke(new Complete(WorkComplete));
}
}
}
}
但是处理的URL的数量总是比总数少一,这几乎就像最后一个线程不是"Reporting back"之类的.有人有什么想法吗?
But the amount of URL's processed is always one less than the total count, it's almost like the last thread isn't 'Reporting back' or something. Does anyone have any ideas?
谢谢
推荐答案
上面的代码中存在一些问题:
There are a few issues in the above code:
- 您要包括异常处理,但是对
Interlocked.Decrement
的调用不在finally块中.这意味着,异常会阻止jobCounter
正常降低. - 您正在锁定每个线程上的方法.这样可以有效地使这些ThreadPool线程中只有一个可以在任何时间执行,因为它们都锁定在同一个变量(
_threadLock
)上.如果需要这样做,则没有理由使用多个线程池线程-只需一个线程就可以循环处理所有项目,因为那实际上就是您现在正在做的事情. - 似乎(虽然代码不是100%清楚的),您正在直接从线程池线程访问UI元素(即:
chkTwitt.Checked
).这不可靠. - 您已将所有内容设置为单个
result
变量,该变量在所有线程之间共享.从实际意义上说,目前尚不清楚该如何使用.
- You're including exception handling, but your call to
Interlocked.Decrement
isn't in the finally block. This means that an exception will prevent thejobCounter
from getting reduced properly. - You're locking within your method, on every thread. This effectively makes it so that only one of these ThreadPool threads can execute at any point in time, since they're all locking on the same variable (
_threadLock
). If this is desired, there's no reason to use multiple thread pool threads - just have one thread process all of the items in a loop, since thats effectively what you're doing now. - It appears (the code isn't 100% clear, though) that you're accessing UI elements from the thread pool threads directly (ie:
chkTwitt.Checked
). This isn't reliable. - You have everything being set into a single
result
variable, which is shared across all of the threads. Its not clear how this would be used, in a practical sense.
鉴于您实际上只是在处理项目(URL)的集合,所以您可能还想考虑使用Parallel.ForEach
甚至PLINQ
来处理项目.
Given that you're effectively just processing a collection of items (URLs), you may want to also consider using Parallel.ForEach
for even PLINQ
to process the items.
这篇关于检查ThreadPool线程何时完成的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!