从C#消耗F#异步

Onu*_*mus 6 f# async-await

假设我有以下代码:

namespace Library1

open System.Threading.Tasks
open System.Threading
open System.Runtime.Remoting.Messaging
open System

type public Class1() =

    let printThread (message) = 
        printfn "%s %A" message Thread.CurrentThread.ManagedThreadId

    let bar = 
        printThread ("first bar")
        async { 
            printThread ("first async")
            do! Async.Sleep(1000)
            printThread "last async"
        }

    member this.X() =  bar
Run Code Online (Sandbox Code Playgroud)

我想使用此类并从C#调用X。问题是X返回Async <'T>。但是,公开F#特定类型是不好的做法。因此,最佳实践是返回任务。但是Async.StartAsTask有点问题,因为它将导致代码在单独的线程中运行。我想要的是我想返回一个Task,但它也应该表现为Async.StartImmediate。因此,代码的非异步部分应在原始主线程中运行。在这里,我假设我从UI线程运行它,以便所有调用都将返回相同的线程ID。换句话说,我想要一个Async.StartImmediate但返回一个任务。这可以实现吗?

Onu*_*mus 2

这完全按照我想要的方式工作(与这个版本返回一个 int 的问题不同,这是加号):

type public Class1() = 
    let printThread (message) = printfn "%s %A" message Thread.CurrentThread.ManagedThreadId

    let bar = 
        printThread ("first bar")
        async { 
            printThread ("first async")
            do! Async.Sleep(1000)
            printThread "last async"
            return 1232
         }

    member this.convertToTask<'T> (asyn : Async<'T>) = 
       let tcs1 = new TaskCompletionSource<'T>()
       let t1 = tcs1.Task
       Async.StartWithContinuations
        (
          asyn 
          , (fun (k) -> tcs1.SetResult(k)), (fun exn -> tcs1.SetException(exn)), fun exn -> ())
        t1

    member this.X() : Task<int> =  (bar |> this.convertToTask)
Run Code Online (Sandbox Code Playgroud)