2016-04-28 5 views
1

私の理解では、あなただけawaitが最終的にTaskの戻りであるasync方法を持っている場合、あなたはasyncawaitキーワードを削除し、ちょうどTaskを返すことができるということです。例えば例外待望のリピータータスクを返すときに、結果

public async Task<object> Handle(object message) 
{ 
    var result = await Task.FromResult(message); 
    return result; 
} 

public Task<object> Handle(object message) 
{ 
    return Task.FromResult(message); 
} 

しかし、このメソッドは、複数のステートメントを待つ含まれている場合に動作していないようになります。例えば

async Task Main() 
{ 
    // outputs: Request 
    var requestHandlerAwaitingResult = (Request) await new HandlerAwaitingResult().Handle(new Request()); 
    Debug.WriteLine(requestHandlerAwaitingResult.Description); 

    // InvalidCastException: Unable to cast object of type 'System.Threading.Tasks.Task`1[System.Object]' to type 'Request'. 
    var requestHandlerReturnTask = (Request) await new HandlerReturningTask().Handle(new Request()); 
    Debug.WriteLine(requestHandlerReturnTask.Description); 
} 

public class Request 
{ 
    public string Description = "Request"; 
} 

public class HandlerAwaitingResult 
{ 
    public async Task<object> Handle(object message) 
    { 
     await Task.Delay(TimeSpan.FromSeconds(1)); 
     var result = await Task.FromResult(message); 
     return result; 
    } 
} 

public class HandlerReturningTask 
{ 
    public async Task<object> Handle(object message) 
    { 
     await Task.Delay(TimeSpan.FromSeconds(1)); 
     return Task.FromResult(message); 
    } 
} 

これが動作しない理由を誰も私を伝えることができますか?

基本的に、私はまだ私は質問を理解していない

public class HandlerReturningTask 
{ 
    public async Task<object> Handle(object message) 
    { 
     await Task.Delay(TimeSpan.FromSeconds(1)); 
     return Task.FromResult(message); 
    } 
} 

public class HandlerReturningTask 
{ 
    public async Task<object> Handle(object message) 
    { 
     await Task.Delay(TimeSpan.FromSeconds(1)); 
     return await Task.FromResult(message); 
    } 
} 

public class HandlerReturningTask 
{ 
    public Task<object> Handle(object message) 
    { 
     return Task.FromResult(message); 
    } 
} 
+3

ステートマシンコンパイラが非同期メソッド用に作成することの理解に基づいて、まずはその理由を説明してください。 –

+0

私は前のコメントに同意し、あなたが何を求めているのか理解していません。あなたが気付いているように、 'async'メソッドの' return'文は、 'Task 'に 'T '型のオブジェクトを返します。あなたの 'HandlerReturningTask'では、' T'は 'object'です。そして、このオブジェクトは 'await'によってアンラップされます。したがって、 'Task 'オブジェクトを返し、 'Result'にキャストしようとします。それはなぜうまくいくのですか? 'return Task.FromResult(message);'の代わりに、単に 'return message;'だけではないでしょうか? –

答えて

1

の違いは何ですか。しかし、あなたの編集に基づいて:

基本的に、[&hellip; return Task.FromResult(message);&hellip;]と[&hellip; return await Task.FromResult(message);&hellip;]

awaitが何をするか理解することが重要である:それはこの方法では、実行後、メソッドが返すことができ、あなたの方法でポイントを表し、そして「awaitable」後で再開することができます(例えばTask )が完了します。

TaskTask<T>ある場合、他の事awaitあるん、この方法で実行を再開する上で、Task<T>オブジェクトのT値を、アンラップすなわち、そのResultプロパティ値を取得します。その値に対する式の評価はawaitです。

最後に、async Task<T>方法のためreturnステートメントはreturn {value}式にResult値を有するように(最初await式で)メソッドによって返さTask<T>オブジェクトを引き起こします。

したがって、return Task.FromResult(message);Task<object>.Resultプロパティの値がTask<Request>のオブジェクトになるようにします。その後、await式は、このオブジェクトのResultプロパティの値を評価し、あなたはもちろん、違法であるタイプRequestのオブジェクトにこれをキャストしてみてください。return await Task.FromResult(message);を使用して

Task<Request>.Resultプロパティ値を取得する効果があり、最初に評価するawait式を(そうreturn文はその式の結果を返すことができます)、原因となります。この値はreturnステートメントによって返され、待たれたTask<object>.Resultの値は、最初にメソッドに渡されたRequestオブジェクトになります。これは、もちろんRequestにキャストすることができます。これは、発信者のawaitによってアンラップされます。

これは、通常は値を直接返すと言っていました。 Task<T>オブジェクトにラップすると、awaitという式ですぐにラップしても意味がありません。そのシナリオでreturn message;を書くと、同じ結果が得られますが、より読みやすく効率的なコードになります。

0

生成されたステートマシンは、任意の待ち状態を処理します。タスクだけでなく、

1つのタスクしか処理していない場合は、コンピュータ生成の状態マシンのオーバーヘッドを回避できます。ただし、例外の場合、スタックトレースは期待どおりにはなりません。

非同期メソッドの戻り値の型は、常に返すもののタスクになります。

関連する問題