Синхронизация задач без потока пользовательского интерфейса

В приведенном ниже коде я хочу синхронизировать отчет о результатах списка задач. Сейчас это работает, потому что task.Result блокируется до завершения задачи. Однако выполнение задачи id = 3 занимает много времени и блокирует все остальные завершенные задачи от сообщения своего статуса.

Я думаю, что могу сделать это, переместив отчет (Console.Write) в файл.Инструкция ContinueWith, но у меня нет потока пользовательского интерфейса, так как мне получить TaskScheduler для синхронизации задач .ContinueWith?

Что у меня сейчас:

static void Main(string[] args)
{
    Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);

    var tasks = new List<Task<int>>();

    for (var i = 0; i < 10; i++)
    {
        var num = i;
        var t = Task<int>.Factory.StartNew(() =>
        {
           if (num == 3)
           {
               Thread.Sleep(20000);
           }
           Thread.Sleep(new Random(num).Next(1000, 5000));
           Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
           return num;
        });
        tasks.Add(t);
    }

    foreach (var task in tasks)
    {
        Console.WriteLine("Completed {0} on {1}", task.Result, Thread.CurrentThread.ManagedThreadId);
    }

    Console.WriteLine("End of Main");
    Console.ReadKey();
}

Я хотел бы перейти к этому или чему-то подобному, но мне нужен Console.Write ("Завершено ..."), чтобы все происходило в одном потоке:

static void Main(string[] args)
{
    Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);

    for (var i = 0; i < 10; i++)
    {
        var num = i;
        Task<int>.Factory.StartNew(() =>
        {
           if (num == 3)
           {
               Thread.Sleep(20000);
           }
           Thread.Sleep(new Random(num).Next(1000, 10000));
           Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
           return num;
       }).ContinueWith(value =>
       {
           Console.WriteLine("Completed {0} on {1}", value.Result, Thread.CurrentThread.ManagedThreadId);
       } 

     /* need syncronization context */);
    }

    Console.WriteLine("End of Main");
    Console.ReadKey();
}

- РЕШЕНИЕ - После получения комментариев и чтения некоторых решений это полное решение, которое делает то, что я хочу. Цель здесь - как можно быстрее обработать несколько длительно выполняющихся задач, а затем сделать что-то с результатами каждой задачи по очереди.

static void Main(string[] args)
{
    Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);

    var results = new BlockingCollection<int>();

    Task.Factory.StartNew(() =>
    {
        while (!results.IsCompleted)
        {
            try
            {
                var x = results.Take();
                Console.WriteLine("Completed {0} on {1}", x, Thread.CurrentThread.ManagedThreadId);
            }
            catch (InvalidOperationException)
            {
            }
        }
        Console.WriteLine("\r\nNo more items to take.");
    });

    var tasks = new List<Task>();

    for (var i = 0; i < 10; i++)
    {
        var num = i;
        var t = Task.Factory.StartNew(() =>
        {
            if (num == 3)
            {
                Thread.Sleep(20000);
            }
            Thread.Sleep(new Random(num).Next(1000, 10000));
            Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
            results.Add(num);
        });

        tasks.Add(t);
    }

    Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => results.CompleteAdding());

    Console.WriteLine("End of Main");
    Console.ReadKey();
}
6
задан Ryan Pedersen 2 July 2011 в 22:50
поделиться