Что не так с моим использованием System.Threading.Tasks.Task? - PullRequest
2 голосов
/ 01 декабря 2011
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 Ответ

1 голос
/ 01 декабря 2011

Я бы сказал, что у вас в тупике где-то в 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

Я могу получить такой же вывод, как и вы, заблокировав один и тот же объект в DoSomething и DoSomethingInternal, хотя в моем случае это первые 7, которые не завершены. работает DoSomething в потоке ThreadPool

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...