次のコードで正常に動作しています。
private void button1_Click(object sender, EventArgs e)
{
Task<int> t = test(5);
Console.WriteLine(t.Result);
}
private Task<int> test(int n)
{
return Task.Run(() =>
{
return n;
});
}
しかし、非同期メソッドでテスト メソッドをラップすると、機能しません。
private Task<int> test(int n)
{
return Task.Run(() =>
{
return n;
});
}
public async Task<int> wrap()
{
return await test(5);
}
private void button1_Click(object sender, EventArgs e)
{
Task<int> t = wrap();
Console.WriteLine(t.Result);
}
フォームは応答を失います。await を使用すると、期待どおりに動作します。
Update1: これら 2 つの回答はどちらも正しいですが、回答としてマークできるのは 1 つだけです。この質問の理解に基づいて、さらにテストを行いました。ラップ メソッドで ConfigureAwait を使用して、継続を UI 以外のスレッドで実行するようにしました。
public async Task<int> wrap()
{
return await test(5).ConfigureAwait(false);
}
それは正常に動作します。そして、私はこれをテストしました:
public async Task<int> wrap()
{
int i = await test(5).ConfigureAwait(false);
int j = i + await test(3);
return j;
}
ボタンをクリックしたときは初めて動作しますが、2回目のクリックで再びデッドロックします。test(3) の後に ConfigureAwait(false) を追加すると、次のようになります。
public async Task<int> wrap()
{
int i = await test(5).ConfigureAwait(false);
int j = i + await test(3).ConfigureAwait(false);
return j;
}
再び機能していますが、これは私には意味がありません。最初の ConfigureAwait(false) のため、wrap() の後続の同期部分はすべて非 UI スレッドで実行する必要があります。2 番目の ConfigureAwait(false) が必要な理由がわかりません。
アップデート2:
private Task<int> test(int n)
{
return Task.Run(() =>
{
Console.WriteLine("test(" + n + "): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return n;
});
}
public async Task<int> wrap()
{
Console.WriteLine("1.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
int i = await test(5).ConfigureAwait(false);
Console.WriteLine("2.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
int j = i + await test(3);
Console.WriteLine("3.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return j;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Console.WriteLine("1.button1_Click(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
var t = wrap();
Console.WriteLine("2.button1_Click(): " + System.Threading.Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(t.Result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
数回クリックすると、フォームがフリーズし、出力は次のようになります。
1.button1_Click(): 8
1.wrap(): 8
test(5): 13
2.wrap(): 8
2.button1_Click(): 8
test(3): 13
驚いたことに、「2.wrap():」は「test(5)」ではなく「1.wrap():」と同じスレッドで実行されています。ConfigureAwait(false) の後のコードも UI スレッドにジャンプできるようです.</p>