c#.netでのスレッド遷移のテスト | 主にDIYのブログ

主にDIYのブログ

ブログの説明を入力しません。

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()    //これは通る
    );
}

こんな感じか。

スレッド遷移周りの理解が甘いなー。ヨクワカラン。