How does F#'s async really work?

前端 未结 6 1073
逝去的感伤
逝去的感伤 2020-12-23 17:01

I am trying to learn how async and let! work in F#. All the docs i\'ve read seem confusing. What\'s the point of running an async block with Async

6条回答
  •  时光取名叫无心
    2020-12-23 17:25

    The usage of async is to save the number of threads in usage.

    See the following example:

    let fetchUrlSync url = 
        let req = WebRequest.Create(Uri url)
        use resp = req.GetResponse()
        use stream = resp.GetResponseStream()
        use reader = new StreamReader(stream)
        let contents = reader.ReadToEnd()
        contents 
    
    let sites = ["http://www.bing.com";
                 "http://www.google.com";
                 "http://www.yahoo.com";
                 "http://www.search.com"]
    
    // execute the fetchUrlSync function in parallel 
    let pagesSync = sites |> PSeq.map fetchUrlSync  |> PSeq.toList
    

    The above code is what you want to do: define a function and execute in parallel. So why do we need async here?

    Let's consider something big. E.g. if the number of sites is not 4, but say, 10,000! Then There needs 10,000 threads to run them in parallel, which is a huge resource cost.

    While in async:

    let fetchUrlAsync url =
        async { let req =  WebRequest.Create(Uri url)
                use! resp = req.AsyncGetResponse()
                use stream = resp.GetResponseStream()
                use reader = new StreamReader(stream)
                let contents = reader.ReadToEnd()
                return contents }
    let pagesAsync = sites |> Seq.map fetchUrlAsync |> Async.Parallel |> Async.RunSynchronously
    

    When the code is in use! resp = req.AsyncGetResponse(), the current thread is given up and its resource could be used for other purposes. If the response comes back in 1 second, then your thread could use this 1 second to process other stuff. Otherwise the thread is blocked, wasting thread resource for 1 second.

    So even your are downloading 10000 web pages in parallel in an asynchronous way, the number of threads are limited to a small number.

    I think you are not a .Net/C# programmer. The async tutorial usually assumes that one knows .Net and how to program asynchronous IO in C#(a lot of code). The magic of Async construct in F# is not for parallel. Because simple parallel could be realized by other constructs, e.g. ParallelFor in the .Net parallel extension. However, the asynchronous IO is more complex, as you see the thread gives up its execution, when the IO finishes, the IO needs to wake up its parent thread. This is where async magic is used for: in several lines of concise code, you can do very complex control.

提交回复
热议问题