2016-09-17 23 views
2

のは、私はこれらのメソッドを持っていると仮定しましょう:パフォーマンスへの影響は待つ

public async Task<Something> GetSomethingAsync() 
{ 
    var somethingService = new SomethingService(); 

    return await service.GetAsync(); 
} 

public Task<Something> GetSomethingAsync() 
{ 
    var somethingService = new SomethingService(); 

    return service.GetAsync(); 
} 

両方のオプションが同じようにコンパイルして動作します。いずれかの方が速い方が良い方が良い方はベストプラクティスですか?

それとも構文的な砂糖ですか?

+1

最初のオプションはタスクの完了を待ちますが、2番目のオプションは完了しません。だから二番目の方がはるかに速くなるでしょう。 – Enigmativity

+1

@Enigmativity、両方のメソッドが同時に呼び出し元に戻ります。しかし、2番目の方法では、 "awating"タスクの責任は呼び出し側に移されます。最初のアプローチでは、タスクが終了したときにコードの実行が返されます。 – Fabio

+0

@Enigmativityいいえ、どちらも同じ動作のタスクを返す –

答えて

1

第1の方法では、コンパイラはタスクの完了後に "ステートマシン"コードを生成し、return await service.GetAsync();行に戻します。ラインDoSomething();service.GetAsyncタスクが完了した後にのみ実行されます

public async Task<Something> GetSomethingAsync() 
{ 
    var somethingService = new SomethingService(); 

    // Here execution returns to the caller and returned back only when Task is completed. 
    Something value = await service.GetAsync(); 

    DoSomething(); 

    return value;   
} 

:以下の例を考えてみましょう。

2番目の方法は、完了を待たずにservice.GetAsyncの実行を開始し、対応するTaskを呼び出し元に返します。だから例のDoSomething()上記

public Task<Something> GetSomethingAsync() 
{ 
    var somethingService = new SomethingService(); 

    Task<Something> valueTask = service.GetAsync(); 

    DoSomething(); 

    return valueTask;   
} 

は、タスクの完了を待たずに直線Task<Something> valueTask = service.GetAsync();後に実行されます。

別のスレッドでasyncメソッドを実行する方法自体によって異なります。

メソッドがIOの操作を実行した場合、別のスレッドはスレッドを無駄にし、何もしません。応答を待つだけです。私の意見ではasync - awaitは、IO操作のための完全なアプローチです。

GetAsyncメソッドがたとえばTask.Runの場合、スレッドプールからフェッチされた別のスレッドに実行が移ります。以下は

は簡単な例ではなく、良いものですが、それは説明しようとしたロジックを示しています。

static async Task GetAsync() 
{ 
    for(int i = 0; i < 10; i++) 
    { 
     Console.WriteLine($"Iterate GetAsync: {i}"); 
     await Task.Delay(500); 
    } 
} 

static Task GetSomethingAsync() => GetAsync(); 

static void Main(string[] args) 
{ 
    Task gettingSomethingTask = GetSomethingAsync(); 

    Console.WriteLine("GetAsync Task returned"); 

    Console.WriteLine("Start sleeping");    
    Thread.Sleep(3000);    
    Console.WriteLine("End sleeping"); 

    Console.WriteLine("Before Task awaiting"); 
    gettingSomethingTask.Wait(); 
    Console.WriteLine("After Task awaited"); 

    Console.ReadLine(); 
} 

、出力は次のようになります。

Iterate GetAsync: 0 
GetAsync Task returned 
Start sleeping 
Iterate GetAsync: 1 
Iterate GetAsync: 2 
Iterate GetAsync: 3 
Iterate GetAsync: 4 
Iterate GetAsync: 5 
End sleeping 
Before Task awaiting 
Iterate GetAsync: 6 
Iterate GetAsync: 7 
Iterate GetAsync: 8 
Iterate GetAsync: 9 
After Task awaited 

をあなたがの実行を見ることができるようにGetAsyncはそれを呼び出した直後に開始します。

GetSomethingAsync()場合に変更されます。別のタスク内にラップGetAsync

static Task GetSomethingAsync() => new Task(async() => await GetAsync()); 

が、その後、GetAsync()が全く実行されず、出力は次のようになります。もちろん

GetAsync Task returned 
Start sleeping 
End sleeping 
Before Task awaiting 
After Task awaited 

必要になります行gettingSomethingTask.Wait();を削除する必要があります。これは、アプリケーションが起動していないタスクを待つためです。

+1

ありがとう!これは意味をなさないようです:) 1つのコメント - あなたの2番目の方法での "非同期"は、身体のどこにいても "待っている"とは言わないので、全く必要ではありません。 – Cumbaja

+0

何か不足していますか?おもう; 2番目の例では、 'valueTask'はまったく実行されません。あなたが 'await'や' valueTask.Start() 'などになるまで。 –

+0

それは良い点です。私は本当にすべてのことで混乱しています。私はそれが何か簡単だろうと思った。 – Cumbaja

関連する問題