0

There is a sample on MSDN for .NET ThreadPool. If I run this code, the output is completely erratic, sometimes, I get a completely empty output on the Console.

If I add a Thread.Sleep() call, even just for a few ms, the output is fine.

AFAIK Console.WriteLine() is thread-safe, so the output should always be there. But its not, at least not on my i7 2600 x64 compiled version. Obviously, if I add a breakpoint everything is fine, but it drives me mad.

I added a ConcurrentBag to make sure stuff is there, but even printing the elements of that is empty. Again, if I add a breakpoint everything is fine.

{
    public class TaskInfo
    {
        public string m_text;

            public int m_value;
        public ConcurrentBag<int> m_bag;
    public TaskInfo(string text, int value, ConcurrentBag<int> bag)
    {
        m_text = text;
        m_value = value;
        m_bag = bag;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    void Run()
    {
        ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();
        for (int i = 0; i < 10; i++)
        {
            TaskInfo ti = new TaskInfo("Hello Thread", i, concurrentBag);
            bool b = ThreadPool.QueueUserWorkItem(new WaitCallback(MyThreadFunction), ti);
            if (!b)
            {
                Console.WriteLine("Damn!");
            }
            //Thread.Sleep(5);
        }

        for (int j = 0; j < concurrentBag.Count; j++)
        {
            Console.WriteLine("This is in the bag: {0}", concurrentBag.ElementAt(j));
        }
    }

    static void MyThreadFunction(object stateInfo)
    {
        TaskInfo ti = (TaskInfo)stateInfo;
        ti.m_bag.Add(ti.m_value);
        Console.WriteLine(ti.m_text + ti.m_value.ToString());
    }
}

}

4

3 回答 3

1

这显然是一个控制台应用程序 - 在您将所有工作项排队后,该Run方法返回并且您的程序立即退出。它不会等待您的工作项完成。至少,Thread.Sleep在运行之后添加一个以允许线程池完成。

正确的做法是使用实​​例数组ManualResetEvent并等待它们全部Set由每个工作线程完成。由于这是一个控制台应用程序,WaitHandle.WaitAll除非您Main使用[STAThread].

于 2011-12-18T20:14:43.657 回答
1

我可以很好地理解输出可以为空。

您将 10 个作业推送到队列中,然后立即开始使用结果。并不是所有的工作都会完成,甚至可能还没有开始。

在调试器中运行时,程序将在您从 MyThreadFunction 中看到 WrtieLine() 之前终止。

于 2011-12-18T20:15:04.783 回答
0

是不是当你创建线程时,你必须加入它们(等到它们完成),直到你尝试打印它们“产生”的任何东西?

如果不是,则您依赖于可以在最后一个循环之前切换线程的调度程序Run。如果没有,最后一个循环会在你的任何线程开始之前执行。

另一方面,Thread.Sleep让调度程序立即切换到其他线程,这可能就是您观察到Thread.Sleep内部没有问题的原因。

于 2011-12-18T20:14:25.033 回答