检查ThreadPool线程何时完成的正确方法? [英] Correct way of checking when ThreadPool threads are done?

查看:88
本文介绍了检查ThreadPool线程何时完成的正确方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种检查线程池中所有线程何时完成其任务的方法.当前,我正在使用一个计数器,该计数器在线程完成其工作时以及在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:

  1. 您要包括异常处理,但是对Interlocked.Decrement的调用不在finally块中.这意味着,异常会阻止jobCounter正常降低.
  2. 您正在锁定每个线程上的方法.这样可以有效地使这些ThreadPool线程中只有一个可以在任何时间执行,因为它们都锁定在同一个变量(_threadLock)上.如果需要这样做,则没有理由使用多个线程池线程-只需一个线程就可以循环处理所有项目,因为那实际上就是您现在正在做的事情.
  3. 似乎(虽然代码不是100%清楚的),您正在直接从线程池线程访问UI元素(即:chkTwitt.Checked).这不可靠.
  4. 您已将所有内容设置为单个result变量,该变量在所有线程之间共享.从实际意义上说,目前尚不清楚该如何使用.
  1. You're including exception handling, but your call to Interlocked.Decrement isn't in the finally block. This means that an exception will prevent the jobCounter from getting reduced properly.
  2. 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.
  3. 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.
  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆