C# 如何从C调用和处理异步F#工作流#

C# 如何从C调用和处理异步F#工作流#,c#,asynchronous,f#,callback,workflow,C#,Asynchronous,F#,Callback,Workflow,我读过一些F#教程,我注意到在F#中执行异步和并行编程比在C#中容易得多。因此,我试图编写一个F库,它将从C调用,并将C函数(委托)作为参数,异步运行 到目前为止,我已经成功地传递了这个函数(我甚至可以取消),但我错过的是如何实现回C#的回调,该回调将在异步操作完成后立即执行。(例如,函数AsynchronousTaskCompleted?)。此外,我还想知道是否可以将(例如进度%)发回F#from then function AsynchronousTask 有人能帮我吗 这是我到目前为止写的

我读过一些F#教程,我注意到在F#中执行异步和并行编程比在C#中容易得多。因此,我试图编写一个F库,它将从C调用,并将C函数(委托)作为参数,异步运行

到目前为止,我已经成功地传递了这个函数(我甚至可以取消),但我错过的是如何实现回C#的回调,该回调将在异步操作完成后立即执行。(例如,函数AsynchronousTaskCompleted?)。此外,我还想知道是否可以将(例如进度%)发回F#from then function AsynchronousTask

有人能帮我吗

这是我到目前为止写的代码(我不熟悉F#,所以下面的代码可能是错误的或实现得很差)

要获得F#异步工作流的好处,您必须实际使用F#编写异步计算。您试图编写的代码将无法工作(即,它可能会运行,但不会有用)

在F#中编写异步计算时,可以使用
let
执行。这允许您使用其他基本的非阻塞计算。例如,您可以使用
Async.Sleep
而不是
Thread.Sleep

// This is a synchronous call that will block thread for 1 sec
async { do Thread.Sleep(1000) 
        someMoreStuff() }

// This is an asynchronous call that will not block threads - it will create 
// a timer and when the timer elapses, it will call 'someMoreStuff' 
async { do! Async.Sleep(1000)
        someMoreStuff() }
只能在
async
块中使用异步操作,这取决于F#compiler处理
的方式
让我们来。对于以顺序方式编写的代码(例如,在C#中或在
async
block in F#之外),没有(简单的)方法可以获得真正的非阻塞执行

如果您想使用F#获得异步工作流的好处,那么最好的选择是在F#中实现操作,然后使用
Async.startask
(这使您可以轻松使用
任务
)。大概是这样的:

let someFunction(n) = async {
  do! Async.Sleep(n)
  Console.WriteLine("working")
  do! Async.Sleep(n)
  Console.WriteLine("done") 
  return 10 }

type AsyncStuff() = 
  member x.Foo(n) = someFunction(n) |> Async.StartAsTask

// In C#, you can write:
var as = new AsyncStuff()
as.Foo(1000).ContinueWith(op =>
    // 'Value' will throw if there was an exception
    Console.WriteLine(op.Value))

如果您不想使用F#(至少在实现异步计算时是这样),那么异步工作流对您没有帮助。您可以使用
任务
BackgroundWorker
或其他C#技术实现类似的功能(但您将失去在不阻塞线程的情况下轻松运行操作的能力)。

代码似乎工作正常,但我不确定它是否应该以这种方式实现。如果我用F#写异步计算,我能从C#使用它吗?谢谢你的回答,我会尝试熟悉异步计算。@loannis:我添加了一些信息和示例,说明如何用F#写异步工作流,并使用
startask
从C#使用它。希望这会有帮助!非常感谢你对我的帮助。谢谢你的提问和回答@Tomas,你知道有没有办法在C中使用F的异步类型,或者你通常会建议让你的F代码C友好,而不是相反?
let someFunction(n) = async {
  do! Async.Sleep(n)
  Console.WriteLine("working")
  do! Async.Sleep(n)
  Console.WriteLine("done") 
  return 10 }

type AsyncStuff() = 
  member x.Foo(n) = someFunction(n) |> Async.StartAsTask

// In C#, you can write:
var as = new AsyncStuff()
as.Foo(1000).ContinueWith(op =>
    // 'Value' will throw if there was an exception
    Console.WriteLine(op.Value))