标签: async-workflow

dotNet中是否存在DirectoryInfo.GetFiles/Directory.GetDirectories的异步版本?

dotNet中是否存在DirectoryInfo.GetFiles/Directory.GetDirectories的异步版本?我想在F#异步块中使用它们,并且拥有一个可以使用AsyncCallbacks调用的版本会很好.

问题是我试图吮吸一堆目录,可能是在慢速网络连接上的SMB挂载上,我不希望一堆线程池线程在等待网络读取时可能正在做其他工作.

.net f# asynchronous directoryinfo async-workflow

40
推荐指数
4
解决办法
2万
查看次数

什么是F#的异步工作流的Scala等价物?

什么是F#的异步工作流的Scala等价物?

例如,如何跟随F#snippet转换为惯用的Scala?

open System.Net
open Microsoft.FSharp.Control.WebExtensions

let urlList = [ "Microsoft.com", "http://www.microsoft.com/"
                "MSDN", "http://msdn.microsoft.com/"
                "Bing", "http://www.bing.com"
              ]

let fetchAsync(name, url:string) =
    async { 
        try
            let uri = new System.Uri(url)
            let webClient = new WebClient()
            let! html = webClient.AsyncDownloadString(uri)
            printfn "Read %d characters for %s" html.Length name
        with
            | ex -> printfn "%s" (ex.Message);
    }

let runAll() =
    urlList
    |> Seq.map fetchAsync
    |> Async.Parallel 
    |> Async.RunSynchronously
    |> ignore

runAll()
Run Code Online (Sandbox Code Playgroud)

f# scala async-workflow

15
推荐指数
1
解决办法
1935
查看次数

在测试F#异步工作流时如何获得有用的堆栈跟踪

我想测试以下异步工作流程(使用NUnit + FsUnit):

let foo = async {
  failwith "oops"
  return 42
}
Run Code Online (Sandbox Code Playgroud)

我为它编写了以下测试:

let [<Test>] TestFoo () =
  foo
  |> Async.RunSynchronously
  |> should equal 42
Run Code Online (Sandbox Code Playgroud)

自从foo抛出后,我在单元测试运行器中得到以下stacktrace:

System.Exception : oops
   at Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously(CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout)
   at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously(FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
   at ExplorationTests.TestFoo() in ExplorationTests.fs: line 76
Run Code Online (Sandbox Code Playgroud)

不幸的是,堆栈跟踪并没有告诉我异常的位置.它在RunSynchronously处停止.

某处我听说Async.Catch神奇地恢复了堆栈跟踪,所以我调整了我的测试:

let [<Test>] TestFooWithBetterStacktrace () =
  foo
  |> Async.Catch
  |> Async.RunSynchronously
  |> fun x -> match x with 
              | Choice1Of2 x -> x |> should equal 42
              | Choice2Of2 …
Run Code Online (Sandbox Code Playgroud)

f# nunit unit-testing async-workflow

13
推荐指数
1
解决办法
784
查看次数

使用异步工作流并行化的最佳实践

让我们说我想刮一个网页,并提取一些数据.我最有可能写这样的东西:

let getAllHyperlinks(url:string) =
    async {  let req = WebRequest.Create(url)
             let! rsp = req.GetResponseAsync()
             use stream = rsp.GetResponseStream()             // depends on rsp
             use reader = new System.IO.StreamReader(stream)  // depends on stream
             let! data = reader.AsyncReadToEnd()              // depends on reader
             return extractAllUrls(data) }                    // depends on data
Run Code Online (Sandbox Code Playgroud)

let!讲述F#在另一个线程来执行代码,然后将结果结合到一个变量,并继续处理.上面的示例使用两个let语句:一个用于获取响应,一个用于读取所有数据,因此它至少生成两个线程(如果我错了,请纠正我).

虽然上面的工作流程会产生多个线程,但执行顺序是串行的,因为工作流程中的每个项目都依赖于前一个项目.在其他线程返回之前,无法在工作流程中进一步评估任何项目.

let!在上面的代码中有多个有什么好处?

如果没有,该代码如何更改以利用多个let!语句?

f# asynchronous async-workflow

8
推荐指数
1
解决办法
1268
查看次数

异步计算不会捕获OperationCancelledException

我正在尝试向URL发出异步Web请求,如果请求耗时太长,将返回该URL.我正在使用F#异步工作流和System.Net.Http库来执行此操作.

但是,我无法捕获async工作流中System.Net.Http库引发的Task/OperationCancelledExceptions .相反,异常是在Async.RunSynchronously方法中引发的,如此堆栈跟踪中所示:

> System.OperationCanceledException: The operation was canceled.    at
> Microsoft.FSharp.Control.AsyncBuilderImpl.commit[a](Result`1 res)   
> at
> Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously[a](CancellationToken
> token, FSharpAsync`1 computation, FSharpOption`1 timeout)    at
> Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync`1
> computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
> at <StartupCode$FSI_0004>.$FSI_0004.main@()
Run Code Online (Sandbox Code Playgroud)

代码:

#r "System.Net.Http"

open System.Net.Http
open System

let readGoogle () = async {
    try
        let request = new HttpRequestMessage(HttpMethod.Get, "https://google.co.uk")
        let client = new HttpClient()
        client.Timeout <- TimeSpan.FromSeconds(0.01) //intentionally low to always fail in this example
        let! response = client.SendAsync(request, HttpCompletionOption.ResponseContentRead) |> Async.AwaitTask …
Run Code Online (Sandbox Code Playgroud)

f# async-workflow task-parallel-library computation-expression

8
推荐指数
1
解决办法
461
查看次数

F#中的ConfigureAwait(false)

我正在使用一个用C#编写的库,并使用async / await模式。在C#中,我可以用调用它来等待某些东西,ConfigureAwait(false)但是当我从F#使用库时,我看不到做相同事情的方法吗?

目前,我确实SomeMethodAsync() |> Async.AwaitTask将其转换为AsyncF#工作流程,但是ConfigureAwait(false)调用时我该如何与F#一样SomeMethodAsync呢?


编辑:

在F#Slack频道中提供了一些出色的帮助,并进行了一些附加的搜索,我在这里找到了关于如何切换上下文的很好的解释:http : //tomasp.net/blog/async-non-blocking-gui.aspx/

c# f# asynchronous async-workflow async-await

7
推荐指数
1
解决办法
370
查看次数

F#异步Web请求,处理异常

我正在尝试在F#中使用异步工作流来获取多个Web请求.

但是,我的一些请求偶尔会返回错误(例如http 500),我不知道如何处理这个问题.看起来我的F#程序在调试器中运行时陷入无限循环.

我可能错过了一些东西,因为我看到的例子没有开箱即用.我找到的第一件事就是帮助了这段代码:

type System.Net.WebRequest with
  member req.GetResponseAsync() =
    Async.BuildPrimitive(req.BeginGetResponse, req.EndGetResponse)
Run Code Online (Sandbox Code Playgroud)

然后我有一些代码来获取请求,这是我见过的例子中非常标准的:

let async_value = async {
  let req = WebRequest.Create(url)
  let! rsp = req.GetResponseAsync()
  return (rsp :?> HttpWebResponse).StatusCode
}
Run Code Online (Sandbox Code Playgroud)

然后我试着得到结果:

let status = Async.RunSynchronously(async_value)
Run Code Online (Sandbox Code Playgroud)

但是当我在调试器中运行我的程序时,它会req.EndGetResponse因为服务器返回内部服务器错误500 而中断.如果我继续执行,它会进入一个时髦的循环,中断req.EndGetResponse(有时连续几次)和let status = Async.RunSynchronously(async_value) .

如何解决异常问题以便获取状态代码?另外,我需要上面做的类型吗?或者我错过了F#/ VS 2010 Beta 1的一些库/ dll,其中这已经是其中的一部分了?

我实际上使用Async.RunSynchronously(Async.Parallel(my_array_of_async_values))并行运行多个请求,尽管我不认为这与我遇到的异常问题有关.

事实上我遇到的例子只是使用Async.Run而不是Async.RunSynchronously可能是一个指标,我错过了一些东西...... = /

f# async-workflow

6
推荐指数
1
解决办法
2177
查看次数

Async.Catch不适用于OperationCanceledExceptions

我使用Async.Catch来处理异步工作流抛出的异常:

work
|> Async.Catch
|> Async.RunSynchronously
|> fun x -> match x with
            | Choice1Of2 _ -> () // success
            | Choice2Of2 ex -> // failure, handle exception
Run Code Online (Sandbox Code Playgroud)

今天我注意到Async.Catch不处理OperationCanceledExceptions.而不是从Async.Catch获得选择,异常不断冒泡直到它击中我.我希望下面的测试是红色的,但它是绿色的:

  [<Test>]
  let ``Async.Catch doesnt work on OperationCancelledExceptions``() =
    use cancellationTokenSource = new System.Threading.CancellationTokenSource(1000)

    let work = async {
      while true do
        do! Async.Sleep 100
    }

    (fun () -> work
               |> Async.Catch
               |> fun x -> Async.RunSynchronously (x, cancellationToken=cancellationTokenSource.Token)
               |> ignore)
    |> should throw typeof<System.OperationCanceledException>
Run Code Online (Sandbox Code Playgroud)

使用Async.Catch + Choices +匹配以及其他一些使用try/catch块评估一些异常似乎不正确......它看起来像下面这样,这太复杂了.除此之外,我想知道Async.Catch有什么用,因为我必须使用try/catch块...:

  [<Test>]
  let ``evaluating …
Run Code Online (Sandbox Code Playgroud)

f# exception-handling async-workflow

6
推荐指数
1
解决办法
944
查看次数

在嵌套循环中并行化代码

您总是听说功能代码本质上比非功能代码更容易并行化,因此我决定编写一个执行以下操作的函数:

给定字符串输入,总计每个字符串的唯一字符数.因此,给定输入[ "aaaaa"; "bbb"; "ccccccc"; "abbbc" ],我们的方法将返回a: 6; b: 6; c: 8.

这是我写的:

(* seq<#seq<char>> -> Map<char,int> *)
let wordFrequency input =
    input
    |> Seq.fold (fun acc text ->
        (* This inner loop can be processed on its own thread *)
        text
        |> Seq.choose (fun char -> if Char.IsLetter char then Some(char) else None)
        |> Seq.fold (fun (acc : Map<_,_>) item ->
            match acc.TryFind(item) with
            | Some(count) -> acc.Add(item, count + 1)
            | None -> acc.Add(item, …
Run Code Online (Sandbox Code Playgroud)

f# multithreading async-workflow

5
推荐指数
1
解决办法
1189
查看次数

为什么我必须将Async <T>包装到另一个异步工作流中并让它!它?

我正在尝试理解F#中的异步工作流程,但我发现有一部分我真的不明白,希望有人可以帮助我.

以下代码工作正常:

let asynWorkflow = async{
    let! result = Stream.TryOpenAsync(partition) |> Async.AwaitTask 
    return result
    } 

let stream = Async.RunSynchronously asynWorkflow
             |> fun openResult -> if openResult.Found then openResult.Stream else Stream(partition)
Run Code Online (Sandbox Code Playgroud)

我定义了一个异步工作流,其中TryOpenAsync返回一个Task类型.我用Async.AwaitTask将它转换为Async.(副任务:"等待"任务?它不等待它只是转换它,是吗?我认为它与Task.Wait或await关键字无关).让我"等待"它!并返回它.要启动工作流,我使用RunSynchronously,它应该启动工作流并返回结果(绑定它).在结果上,我检查是否找不到流.

但现在是我的第一个问题.为什么我必须在另一个异步计算中包装TryOpenAsync调用并让它!("等待")吗?例如,以下代码不起作用:

let asynWorkflow =  Stream.TryOpenAsync(partition) |> Async.AwaitTask  

let stream = Async.RunSynchronously asynWorkflow
             |> fun openResult -> if openResult.Found then openResult.Stream else Stream(partition)
Run Code Online (Sandbox Code Playgroud)

我认为AwaitTask使它成为Async和RunSynchronously应该启动它.然后使用结果.我错过了什么?

我的第二个问题是为什么有"Async.Let!" 功能可用?也许是因为它不起作用或更好,为什么它不适用于以下代码?

let ``let!`` task = async{
    let! result = task |> Async.AwaitTask 
   return result
   } 

let stream = Async.RunSynchronously ( ``let!`` (Stream.TryOpenAsync(partition))  )
         |> fun …
Run Code Online (Sandbox Code Playgroud)

f# asynchronous let async-workflow

5
推荐指数
1
解决办法
142
查看次数