将C#异步方法转换为F#函数

Ben*_*erg 2 f#

我想将下面的C#方法DelayNe转换为F#函数,以便以完全相同的方式从C#中使用它.原因是我想把它放在一个F#库中.我正在苦苦挣扎,试图谷歌我的答案,显然没有运气.

更新:抱歉不清楚.我的任务以您在下面的DelayNe方法中看到的方式调用Task.Delay.问题是,当调用_cancellationTokenSource.Cancel()时,Task.Delay会抛出异常,我不想要那个异常.换句话说,我相信我需要一个围绕Task.Delay的包装器,它将捕获异常并使其静音,但是否则会完全暴露Task.Delay的行为.我想在F#中实现包装器.

private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

async Task DelayNe(int milliSeconds, CancellationToken token)
{
    try
    {
        await Task.Delay(milliSeconds, token);
    }
    catch (TaskCanceledException ex)
    {
        ("Silencing " + ex.GetType().Name + ", " + ex.Message).Dump();
    }
}

async Task Test(CancellationToken cancellationToken)
{
    try
    {
        "Test start".Dump();
        await DelayNe(5000, cancellationToken);
        "Test stop".Dump();
    }
    catch (Exception ex)
    {
        ("Catch: " + ex.Message + ", " + ex.GetType().Name).Dump();
    }
}

async Task Main()
{
    "Start".Dump();
    _cancellationTokenSource.CancelAfter(1000);
    var testTask = Test(_cancellationTokenSource.Token);
    await testTask;
    "Stop".Dump();
}
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 6

F#异步工作流具有内置的取消支持功能,因此使用这些工具而不是使用任务可能会让您的生活更加轻松.你的问题并没有真正提供足够的信息来理解你想要做什么,但下面是一个使用async非常接近你的例子的例子:

let delayNe ms = async {
  use! _d = Async.OnCancel(fun () -> 
    printfn "cancelled!")
  do! Async.Sleep(ms) }

let test = async {
  printfn "Test start"
  do! delayNe 5000
  printfn "Test stop" }

let DoWork () = 
  let cts = new System.Threading.CancellationTokenSource()
  cts.CancelAfter(1000)
  Async.StartAsTask(test, cancellationToken = cts.Token)
Run Code Online (Sandbox Code Playgroud)

DoWork函数将工作作为一项任务启动,可以很容易地从C#中使用.