gpt4 book ai didi

c# - 从 F# 调用 C# 异步方法会导致死锁

转载 作者:行者123 更新时间:2023-12-03 17:28:55 24 4
gpt4 key购买 nike

我有一组 F# 脚本,它们调用我们创建的各种库,其中许多公开了最初用 C# 编写的异步方法。最近我发现脚本停止工作了(我想距离我上次使用它们大约有半年时间了,然后它们工作了)。

我试图隔离问题并想出了以下重现它的代码:

首先,让我们考虑一个包含以下 C# 类的库:

    public class AsyncClass
{
public async Task<string> GetStringAsync()
{
var uri = new Uri("https://www.google.com");
var client = new HttpClient();
var response = await client.GetAsync(uri);
var body = await response.Content.ReadAsStringAsync();
return body;
}
}

接下来,让我们使用以下代码从 F#(FSX 脚本)调用库:
let asyncClient = AsyncClass()

let strval1 = asyncClient.GetStringAsync() |> Async.AwaitTask |> Async.RunSynchronously
printfn "%s" strval1

let strval2 =
async {
return! asyncClient.GetStringAsync() |> Async.AwaitTask
} |> Async.RunSynchronously
printfn "%s" strval2

获取 strval1以死锁告终,而 strval2被检索得很好(我很确定第一个场景在几个月前也可以使用,所以看起来可能是某种更新导致了这种情况)。

这很可能是一个同步上下文问题,其中线程基本上是“等待自己完成”,但我不明白第一次调用到底有什么问题 - 我看不出有什么问题。

StackOverflow 上的类似问题:
  • Why do I have to wrap an Async<T> into another async workflow and let! it? - 这似乎是同一个问题,但没有提供足够的信息,并且缺少一个简单的复制示例
  • Why is Async.RunSynchronously hanging? - 这很相似,但作者犯了一个明显的错误
  • 最佳答案

    所以.net Task将立即开始,而 F# async {}很懒。因此,当您将任务包装在 async { } 中时它变得懒惰,从而具有 Async.RunSynchronously 的特征正在期待。

    通常我只在执行 f# 异步操作时使用 async {},如果我使用 .net 任务,我将使用 TaskBuilder.fs (在 nuget 中可用)。更了解TaskConfigureAwait(continueOnCapturedContext: false) 这样的特质.

    open FSharp.Control.Tasks.V2.ContextInsensitive

    task {
    let! x = asyncClient.GetStringAsync()
    //do something with x
    }

    关于c# - 从 F# 调用 C# 异步方法会导致死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57869267/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com