私はちょうどTask.WhenAllのオーバーロードの1、私は、次の短いプログラムでこの機能を試してみようと思いましたパラメータTask.WhenAll(IEnumerable):タスクは2回開始されますか?
public static Task WhenAll(IEnumerable<Task<TResult>> tasks)
などのIEnumerableを取る1つまずきました。 Testクラスで
:
// contains the task numbers that has been run
private HashSet<int> completedTasks = new HashSet<int>();
// async function. waits a while and marks that it has been run:
async Task<int> Calculate(int taskNr)
{
string msg = completedTasks.Contains(taskNr) ?
"This task has been run before" :
"This is the first time this task runs";
Console.WriteLine($"Start task {i} {msg}");
await Task.Delay(TimeSpan.FromMilliseconds(100));
Console.WriteLine($"Finished task {taskNr}");
// mark that this task has been run:
completedTasks.Add(taskNr);
return i;
}
// async test function that uses Task.WhenAll(IEnumerable)
public async Task TestAsync()
{
Console.Write("Create the task enumerators... ");
IEnumerable<Task<int>> tasks = Enumerable.Range(1, 3)
.Select(i => Calculate(i));
Console.WriteLine("Done!");
Console.WriteLine("Start Tasks and await");
await Task.WhenAll(tasks);
Console.WriteLine("Finished waiting. Results:");
foreach (var task in tasks)
{
Console.WriteLine(task.Result);
}
}
が最後にメインプログラム:以下のように
static void Main(string[] args)
{
var testClass = new TestClass();
Task t = Task.Run(() => testClass.TestAsync());
t.Wait();
}
出力は次のようになります。
Create the task enumerators... Done!
Start Tasks and wait
Start task 1 This is the first time this task runs
Start task 2 This is the first time this task runs
Start task 3 This is the first time this task runs
Finished task 2
Finished task 3
Finished task 1
Finished waiting. Results:
Start task 1 This task has been run before
Finished task 1
1
Start task 2 This task has been run before
Finished task 2
2
Start task 3 This task has been run before
Finished task 3
3
はどうやら各タスクが二回実行されます!私は間違って何をしていますか?
見知らぬ人:Task.Whenallの前にToList()
を使用してタスクのシーケンスを列挙すると、この関数は期待どおりに機能します。
"この機能は非同期ではなく、待ち受けることができません" - それは*待ち受けています。関数は待つことができるように 'async'としてマークする必要はありません - 待ち時間のある待ち行列のパターンに続くものを返さなければなりません。 'Task'はパターンの* poster子です。 –
Sprry、それは私の最初のバージョンでした。後でそれが問題になることがわかったので、すべてを非同期に変更しました。質問を修正しました –