我的System.Threading.Tasks.Task使用有什么问题?

时间:2011-12-01 07:36:06

标签: multithreading c#-4.0

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public sealed class Foo
{
    public int ID;

    private static readonly Dictionary<int, Foo> Instances = new Dictionary<int, Foo>();

    public static void FillInstances()
    {
        // here's some magic code to fill .Instances
    }

    public static void DoSomething()
    {
        var tasks = new Task[Instances.Count];
        var i = 0;
        foreach (var foo in Instances.Values)
        {
            var instance = foo; // just to break the reference
            var task = Task.Factory.StartNew(instance.DoSomethingInternal);
            tasks[i++] = task;
            Logger.DebugFormat("translation: task #{0} = id {1}", task.Id, instance.ID);
        }
        using (var timer = new Timer(callback =>
        {
            Logger.DebugFormat("--------------------- {0}", DateTime.Now);
            foreach (var task in tasks)
            {
                var taskInstance = task; // just to break the reference
                Logger.DebugFormat("task #{0}: {1}", taskInstance.Id, taskInstance.Status);
            }
        }, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)))
        {
            Task.WaitAll(tasks);
            Logger.Debug("ready");
        }
    }

    private void DoSomethingInternal()
    {
        Logger.DebugFormat("DoSomethingInternal / task #{0} - id {1}", Task.CurrentId, this.ID);
    }
}

应该明确说明:我正在调用静态方法DoSomething来并行调用实例方法DoSomethingInternal

输出我的控制台是:

translation: task #1 = id 9
translation: task #2 = id 5
translation: task #3 = id 2
translation: task #4 = id 3
translation: task #5 = id 7
translation: task #6 = id 8
translation: task #7 = id 1
translation: task #8 = id 10
DoSomethingInternal / task #8 - id 10
DoSomethingInternal / task #7 - id 1
DoSomethingInternal / task #6 - id 8
DoSomethingInternal / task #5 - id 7
DoSomethingInternal / task #4 - id 3
--------------------- 12/01/2011 08:29:57
task #1: Running
task #2: Running
task #3: Running
task #4: RanToCompletion
task #5: RanToCompletion
task #6: RanToCompletion
task #7: RanToCompletion
task #8: RanToCompletion
--------------------- 12/01/2011 08:29:58
task #1: Running
task #2: Running
task #3: Running
task #4: RanToCompletion
task #5: RanToCompletion
task #6: RanToCompletion
task #7: RanToCompletion
task #8: RanToCompletion
--------------------- 12/01/2011 08:29:59
task #1: Running
task #2: Running
task #3: Running
task #4: RanToCompletion
task #5: RanToCompletion
task #6: RanToCompletion
task #7: RanToCompletion
task #8: RanToCompletion

显然,任务#1,#2,#3永远不会开始,但.Status个实例的System.Threading.Tasks.Task告诉我们它是Running。 那么这里的问题是什么?

1 个答案:

答案 0 :(得分:1)

我会说你在DoSomethingInternal的某个地方遇到了死锁,你的输出看起来与我线性相当。

当我运行代码时,使用Console.WriteLine作为两种记录器方法,输出为:

translation: task #1 = id 0
DoSomethingInternal / task #1 - id 0
translation: task #2 = id 1
translation: task #3 = id 2
DoSomethingInternal / task #2 - id 1
DoSomethingInternal / task #3 - id 2
DoSomethingInternal / task #4 - id 3
translation: task #4 = id 3
translation: task #5 = id 4
DoSomethingInternal / task #5 - id 4
DoSomethingInternal / task #6 - id 5
translation: task #6 = id 5
translation: task #7 = id 6
translation: task #8 = id 7
DoSomethingInternal / task #7 - id 6
DoSomethingInternal / task #8 - id 7
translation: task #9 = id 8
translation: task #10 = id 9
DoSomethingInternal / task #10 - id 9
DoSomethingInternal / task #9 - id 8
ready

我可以通过锁定DoSomethingDoSomethingInternal中的同一个对象来获得类似的输出,尽管在我的情况下它是第7个不能完成的。 DoSomething主题

上运行ThreadPool