2011-11-05 3 views
32

私はF#でC#ライブラリを使用しようとしています。ライブラリはasync/awaitを大量に使用します。私はF#のasync { ... }ワークフローの中で使用したいです。プレーンタスクでAsync.AwaitTaskを実行する方法(タスクではない<T>)?

非同期C#メソッドでAsync.AwaitTaskを返すと、Task<T>を返すことがありますが、平文を返すものについてはどうでしょうかTask

おそらく、Async<unit>にこれらを変換するか、Task<unit>からTaskはそれがAsync.AwaitTaskで動作します変換するために、ヘルパーはありますか?無限のタイムアウトで

let awaitTask (t: Task) = t.ContinueWith (fun t ->()) |> Async.AwaitTask 

またはAwaitIAsyncResult:

答えて

43

あなたはContinueWithを使用することができます

let awaitTask (t: Task) = t |> Async.AwaitIAsyncResult |> Async.Ignore 
+10

ああ、私は参照してください。もちろん、Taskは結局のところIAsyncResultです。 'awaitTask = Async.AwaitIAsyncResult >> Async.Ignore'に短縮しました。ありがとうございました! – AshleyF

10

私は本当に機能組成物を用いて、アシュリーの提案が好きでした。さらに、Asyncモジュールを次のように拡張することができます。

module Async = 
    let AwaitTaskVoid : (Task -> Async<unit>) = 
     Async.AwaitIAsyncResult >> Async.Ignore 

次に、Async.AwaitTaskとともにIntellisenseに表示されます。これは次のように使用できます:

do! Task.Delay delay |> Async.AwaitTaskVoid 

良い名前を教えてください。

12

更新:

のF#4.0のFSharp.Coreライブラリは現在、プレーンTaskを受け入れAsync.AwaitTask過負荷を含んでいます。 F#4.0を使用している場合は、以下のコードの代わりにこのコア関数を使用する必要があります。


オリジナルの答え:

あなたのタスクは、あなたはおそらくこれをチェックしたい例外をスローすることができれば。例えば適切に適切な例外とキャンセルの両方を伝播する

let awaitTask (task : Task) = 
    async { 
     do! task |> Async.AwaitIAsyncResult |> Async.Ignore 
     if task.IsFaulted then raise task.Exception 
     return() 
    } 
+0

'raise task.Exception'はAggregateExceptionを発生させます。 'InnerExceptions'コレクションにアクセスして最初のコレクションを呼び出すほうが良いでしょう(コレクションが空でない限り) –

1

、私はあなたがこの(部分的にトマーシュPetříčekによって削除された回答に基づいて)のような何か必要だと思う

module Async = 
    let AwaitVoidTask (task : Task) : Async<unit> = 
     Async.FromContinuations(fun (cont, econt, ccont) -> 
      task.ContinueWith(fun task -> 
       if task.IsFaulted then econt task.Exception 
       elif task.IsCanceled then ccont (OperationCanceledException()) 
       else cont()) |> ignore) 
関連する問題