Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 如何在普通任务(而不是任务<;T>;)上异步.AwaitTask?_F#_Async Await - Fatal编程技术网

F# 如何在普通任务(而不是任务<;T>;)上异步.AwaitTask?

F# 如何在普通任务(而不是任务<;T>;)上异步.AwaitTask?,f#,async-await,F#,Async Await,我正试图在F中使用一个C库。该库大量使用async/await。我想在F#中的异步{…}工作流中使用 我知道我们可以对返回Task的异步C方法执行Async.waittask,但是那些返回普通Task的方法呢 也许,是否有帮助程序将这些转换为Async,或者将Task转换为Task,这样它将与Async.waittask一起工作?您可以使用ContinueWith: let awaitTask (t: Task) = t.ContinueWith (fun t -> ()) |> A

我正试图在F中使用一个C库。该库大量使用async/await。我想在F#中的
异步{…}
工作流中使用

我知道我们可以对返回
Task
的异步C方法执行
Async.waittask
,但是那些返回普通
Task
的方法呢


也许,是否有帮助程序将这些转换为
Async
,或者将
Task
转换为
Task
,这样它将与
Async.waittask
一起工作?

您可以使用ContinueWith:

let awaitTask (t: Task) = t.ContinueWith (fun t -> ()) |> Async.AwaitTask
或等待无限超时的同步结果:

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

更新:

F#4.0的FSharp.Core库现在包含一个接受普通任务的Async.AwaitTask重载。如果您使用的是F#4.0,那么您应该使用这个核心函数,而不是下面的代码

原始答案:

我真的很喜欢Ashley使用函数组合的建议。此外,您可以像这样扩展异步模块:

module Async =
    let AwaitTaskVoid : (Task -> Async<unit>) =
        Async.AwaitIAsyncResult >> Async.Ignore
do! Task.Delay delay |> Async.AwaitTaskVoid

有没有更好的名字的建议?

更新:

F#4.0的FSharp.Core库现在包括一个
Async.AwaitTask
重载,它接受一个普通的
任务。如果您使用的是F#4.0,那么您应该使用这个核心函数,而不是下面的代码


原始答案:

如果您的任务可能引发异常,那么您可能还需要检查此异常。e、 g

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

为了正确地传播异常和取消,我认为您需要这样的东西(部分基于TomášPetříček删除的答案):

模块异步=
让任务(任务:任务):异步=
Async.FromContinuations(乐趣(cont,econt,ccont)->
任务。继续(有趣的任务->
如果task.IsFaulted,则econt task.Exception
elif task.iscancelled然后ccont(OperationCanceledException())
else cont())|>忽略)

啊,我明白了。当然,任务毕竟是一个iSyncResult。缩短为
let awaitask=Async.awaiiasyncresult>>Async.Ignore
非常感谢!ContinueWith不是惯用的F#,而且它很危险,因为它可能引发TaskCanceledException
引发task。Exception
只会引发AggregateException;最好访问它的
InnerExceptions
集合,并引发第一个集合(只要集合不是空的)
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)