2017-11-20 5 views
2

UIベースではないアプリケーション(ASP.NET)とUIベースのアプリケーション(WinFormとWPF)の両方について、次のようなライブラリがあるとします。残念ながらIOバインド作業とCPUバインド作業を混同することは避けられませんが、Task.Run経由でDummyWorkAsyncを呼び出すか、アプリケーションタイプ(非UIベースまたはUIベースのアプリケーション)に基づいて消費者に呼び出させます。通常のラムダと非同期のラムダとの間に違いはありますか?

class DummyService 
{ 
    public static async Task<int> DummyWorkAsync() 
    { 
    // Do some I/O first. 
    await Task.Delay(1000); 

    // Tons of work to do in here! 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    // Possibly some more I/O here. 
    await Task.Delay(1000); 

    // More work. 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    return 0; 
    } 
} 

これは、UIベースの消費者が適切に次のようにASP.NETクライアントはちょうど直接メソッドを呼び出すだろうが、サービスを呼び出すためにTask.Runを使用することができます。

private async void MyButton_Click(object sender, EventArgs e) 
{ 
    await Task.Run(() => DummyService.DummyWorkAsync()); 
} 

public class Home: Controller 
{ 
    public async Task<ActionResult> IndexAsync() 
    { 
    var result = await DummyService.DummyWorkAsync(); 
    return View(result); 
    } 
} 

質問

私はUIベースのアプリケーションに興味があります。私は

private async void MyButton_Click(object sender, EventArgs e) 
{ 
    await Task.Run(async() => await DummyService.DummyWorkAsync()); 
} 

ではなく

private async void MyButton_Click(object sender, EventArgs e) 
{ 
    await Task.Run(() => DummyService.DummyWorkAsync()); 
} 

を使用している場合は任意の違いはありますか?

+0

:最初は残りの(重いCPUの仕事を)待った後、あなたが最初の場所でTask.Runを使用する必要はありません(少なくともデフォルトのスケジューラを持つ)、ので、その場合には、スレッドプールのスレッド上で実行されます最初のものは、 'DummyWorkAsync'がUIスレッドで終了した後に何かをする必要がある場合にのみ役に立ちます。つまり、実際には終了するのを実際に待っていますが、UIスレッドをブロックしません。 – juharr

+0

@Clemens:「ハイブリッド」の「DummyWorkAsync」にCPUバインドされた作品がいくつか存在するためです。このようなハイブリッド非同期メソッドには、UIベースのアプリケーションで 'Task.Run'を使う必要があります。 –

+1

あなたのIOが最初に行くから(私は最初にTask.Delayを待っています)なぜそれにConfigureAwait(false)を追加しないのですか?その後、Task.RunをラップすることなくUIから呼び出すことができます。 – Evk

答えて

3

いいえ、重要な違いはありません。あなたは、基本的には、1つの以上のラッピングタスク(Task.Run)がある

static Task<int> Something() { 
    return SomethingAsync(); 
} 

static async Task<int> Something() { 
    return await SomethingAsync(); 
} 

の違いは、あなたのケースを除いて何を求めているので、あなたは別で見つける例えば、例外の伝播の違いこの場合、同じ問題に関する質問は関係ありません。そのための

- ちょうどそれは明らかではないことの理由、と述べ

await Task.Run(() => DummyService.DummyWorkAsync()); 

を使用しています。あなたのIOが最初になるので、ConfigureAwait(false)を使用して、現在の同期コンテキストに制御を戻すのを防ぐことができます(これは、とにかくライブラリにとっては良い方法です)。

public static async Task<int> DummyWorkAsync() 
{ 
    // Do some I/O first. 
    await Task.Delay(1000).ConfigureAwait(false); 

    // Tons of work to do in here! 
    // no problem, we are not on UI thread anyway 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    // Possibly some more I/O here. 
    await Task.Delay(1000).ConfigureAwait(false); 

    // More work. 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    return 0; 
} 
関連する問題