线程池 - 可能的线程执行顺序问题 [英] Threadpools - possible thread execution order problem

查看:334
本文介绍了线程池 - 可能的线程执行顺序问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在学习如何使用线程池,但我不知道每个池中的线程都被正确执行,我怀疑一些正在执行一次以上。我已经削减了代码到最低限度,并已使用的Debug.WriteLine,试图找出到底是怎么回事,但是这会产生一些奇怪的结果。

I've been learning how to use the threadpools but I'm not sure that each of the threads in the pool are being executed properly and I suspect some are being executed more than once. I've cut down the code to the bare minimum and having been using Debug.WriteLine to try and work out what is going on but this produces some odd results.

我的代码如下所示(基于(的为WaitAll用于在STA线程多个句柄不支持):

My code is as follows (based on code from (WaitAll for multiple handles on a STA thread is not supported.):

public void ThreadCheck()
    {
        string[] files;
        classImport Import;
        CountdownEvent done = new CountdownEvent(1);
        ManualResetEvent[] doneEvents = new ManualResetEvent[10];

        try
        {
            files = Directory.GetFiles(importDirectory, "*.ZIP");

            for (int j = 0; j < doneEvents.Length; j++)
            {
                done.AddCount();
                Import = new classImport(j, files[j], workingDirectory + @"\" + j.ToString(), doneEvents[j]);
                ThreadPool.QueueUserWorkItem(
                (state) =>
                {
                    try
                    {
                        Import.ThreadPoolCallBack(state);
                        Debug.WriteLine("Thread " + j.ToString() + " started");
                    }
                    finally
                    {
                        done.Signal();
                    }
                }, j);

            }

            done.Signal();
            done.Wait();                            
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Error in ThreadCheck():\n" + ex.ToString());
        }
    }



classImport.ThreadPoolCallBack实际上并没有做任何事情分钟。

The classImport.ThreadPoolCallBack doesn't actually do anything at the minute.

如果我通过代码手动步骤获得:

If I step through the code manually I get:

主题1日开始
线程2开始
....一路....
线10开始

Thread 1 started Thread 2 started .... all the way to .... Thread 10 started

但是,如果我运行它手动输出窗口充满以10线程启动

However, if I run it manually the Output window is filled with "Thread 10 started"

我的问题是:是有什么错我的代码使用线程池的或者中的Debug.WriteLine的结果正由多个线程混淆?

My question is: is there something wrong with my code for use of the threadpool or is the Debug.WriteLine's results being confused by the multiple threads?

推荐答案

的问题是,你使用的循环变量(Ĵ)的lambda表达式中的

The problem is that you're using the loop variable (j) within a lambda expression.

为什么这是一个问题的细节是相当冗长 - 看的埃里克利珀的博客文章的详细信息(也读<一个HREF =http://blogs.msdn.com/b/ericlippert/archive/2009/11/16/closing-over-the-loop-variable-part-two.aspx相对=nofollow>第2部分< 。/ A>)

The details of why this is a problem are quite longwinded - see Eric Lippert's blog post for details (also read part 2).

幸运的是,修复很简单:只需创建一个新的局部变量的 回路,并使用lambda表达式中:

Fortunately the fix is simple: just create a new local variable inside the loop and use that within the lambda expression:

for (int j = 0; j < doneEvents.Length; j++)
{
    int localCopyOfJ = j;

    ... use localCopyOfJ within the lambda ...
}



中使用localCopyOfJ

有关循环体它的优良只使用Ĵ的其余部分 - 当它是由一个lambda表达式或匿名方法,它成为一个问题捕获它只有

For the rest of the loop body it's fine to use just j - it's only when it's captured by a lambda expression or anonymous method that it becomes a problem.

这是一个常见的问题,它绊倒了很多人 - C#团队已考虑修改的行为的foreach 循环(它的真正的看起来你已经宣布在每次迭代一个独立的变量),但它会导致有趣的兼容性问题。 (你可以写C#代码5工作正常,并用C#4可能编译罚款,但真正被打破,例如。)

This is a common issue which trips up a lot of people - the C# team have considered changes to the behaviour for the foreach loop (where it really looks like you're already declaring a separate variable on each iteration), but it would cause interesting compatibility issues. (You could write C# 5 code which works fine, and with C# 4 it might compile fine but really be broken, for example.)

这篇关于线程池 - 可能的线程执行顺序问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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