c#.netでのマルチスレッド云々の話。
ボタンのハンドラ内で、
Task task = Task.Delay(4000);
task.ContinueWith((t)=>{ textBox3.Text = "hoge"; }, TaskContinuationOptions.ExecuteSynchronously);
↑これだとスレッド跨いだUI操作で例外発生。(ただしDebugビルド時のみ。Releaseビルド時には出ない!)
Task.Delay()は別スレッドを返し、そのスレッドでContinueWith()するから?
task.ContinueWith((t) => { textBox3.Text = "hoge"; }, TaskScheduler.FromCurrentSynchronizationContext());
↑これなら通る。
強制的にUIスレッドでContinueWith()させてるから?
あるいは、
private async Task aaa()
{
await Task.Delay(4000);
}
private void button3_Click(object sender, EventArgs e)
{
Task task = aaa();
task.ContinueWith((t)=>{ textBox3.Text = "hoge"; }, TaskContinuationOptions.ExecuteSynchronously);
}
↑これも通る。
Task.Delay()が返す別スレッドはawaitで消化され、aaa()もContinueWith()もUIスレッドで実行されるから?
だから
await Task.Delay(4000).ConfigureAwait(false);
↑こうすると通らない。
await以降も別スレッド継続させ、その別スレッドでContinueWith()を実行させてるから?
だから
task.ContinueWith((t) => { textBox3.Text = "hoge"; }, TaskScheduler.FromCurrentSynchronizationContext());
↑こうすれば通る。
強制的にUIスレッドでContinueWith()させてるから?
なので、遡って、Task.Run()でaaa()自体を別スレッドにした場合、
private async Task aaa()
{
await Task.Delay(4000);
}
private void button3_Click(object sender, EventArgs e)
{
Task task = Task.Run(() => aaa());
//Task task = Task.Run(async () => await aaa()); //こっちでもほぼ同じ
task.ContinueWith((t)=>{ textBox3.Text = "hoge"; },
TaskContinuationOptions.ExecuteSynchronously //これは通らず
TaskScheduler.FromCurrentSynchronizationContext() //これは通る
);
}
こんな感じか。
スレッド遷移周りの理解が甘いなー。ヨクワカラン。