在下面的代碼中,我想同步任務列表的結果報告。這是因爲task.Result阻塞,直到任務完成。但是,任務ID = 3需要很長時間才能完成,並阻止所有其他已完成的任務報告其狀態。沒有UI線程的任務同步
我認爲我可以通過將報告(Console.Write)移動到.ContinueWith指令中,但我沒有UI線程,因此如何獲取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();
}
我假設控制檯線程是一個替身的GUI(的WinForms/WPF)。這不是一個好主意,Dispatcher/Messageloop的存在會造成(很大的)差異。 –
否則,請思考「在同一個線程上發生的事情」。除非該線程正在輪詢,否則不能這樣做。 –
我需要對其進行更改,以便一次只運行一個ContinueWith任務。不管他們是否在同一個線程上運行,但我不能讓他們中的兩個並行運行。在現實生活中,ContinueWith部分將大量數據寫入數據庫。 –