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

2024-04-13

我有一组 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 上的类似问题:

  • 为什么我必须将 Async 包装到另一个异步工作流程中并让!它? https://stackoverflow.com/questions/47330249/why-do-i-have-to-wrap-an-asynct-into-another-async-workflow-and-let-it- 这似乎是同一个问题,但没有给出足够的信息,并且缺少一个简单的重现示例
  • 为什么 Async.RunSynchronously 挂起? https://stackoverflow.com/questions/52229404/why-is-async-runsynchronously-hanging- 这很相似,但作者犯了一个明显的错误

所以一个.netTask将立即开始,而 F#async {}很懒。因此,当您将任务包装在async { }它变得懒惰,因此将具有以下特征:Async.RunSynchronously正在期待。

一般来说,我仅在执行 f# 异步操作时使用 async {},如果我正在使用 .net 任务,我将使用任务生成器.fs https://github.com/rspeele/TaskBuilder.fs(在 nuget 中可用)。是比较了解的Task诸如此类的特质ConfigureAwait(continueOnCapturedContext: false).

open FSharp.Control.Tasks.V2.ContextInsensitive

task {
    let! x = asyncClient.GetStringAsync()
    //do something with x
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 F# 调用 C# 异步方法会导致死锁 的相关文章

随机推荐

  • 等待由 IContextMenu.InvokeCommand 启动的进程

    我有一个TListView其项目是文件 用户可以通过双击它们来打开它们 为此 我将文件保存在 Windows 临时文件夹中 启动一个线程来打开保存的文件ShellExecuteEx 并让它等待ShellExecuteInfo hProces
  • 为什么 tee 等待所有子 shell 完成?

    我有一个运行 mysqld 的服务器脚本并分叉以继续运行 举个例子 mysqld
  • 在 Java 中设置 BufferedImage alpha 掩码

    我有两个从 png 加载的 BufferedImage 第一个包含图像 第二个包含图像的 alpha 蒙版 我想通过应用 alpha 蒙版从这两个图像创建一个组合图像 我的谷歌搜索失败了 我知道如何加载 保存图像 我只需要从两个 Buffe
  • 允许 cPanel 管理 SetEnv 参数

    我们有一个应用程序 它使用 Apache 环境参数来确定它应该使用什么配置 该应用程序的大约 5 个实例托管在一台 cPanel WHM 开发服务器上 我们可以使用 htaccess设置正确的环境 但这会导致未提交的更改 cPanel 应通
  • 是否有关于 HTML 资源包的建议?

    是否有 HTML 资源包的提案 RFC 或者已经有一个标准而我错过了机会 资源束的概念很好地适用于PDF Java 的JAR 闪光的SWF 安卓的APK ETC 看来 WWW 在这里落后了 这是我的非正式建议 允许捆绑所有页面 特定资源 i
  • mysql 假选择

    我的目的是 从值列表中获取多行 例如 1 2 3 4 5 a b c anything 等 mysql gt select id from accounts where id in 1 2 3 4 5 6 id 1 2 3 5 6 5 ro
  • 使用特定网络接口执行请求

    是否可以使用特定的网络接口在 NodeJS 中执行 GET POST 请求 IE 使用 CURL 我可以调用两个 POST 调用 例如 curl X POST interface wlan0 http 192 168 1 5 resourc
  • 新改版(2015 年 9 月)iTunes connect UI 中 iOS 应用程序客户评论部分在哪里

    很抱歉这个明显愚蠢的问题 但是有谁能够找到新改版 2015 年 9 月 的 iTunes connect UI 中客户评论部分已移至何处 在之前的界面迭代中 当您在 iTunes connect 中选择应用程序时 会有一个 评论 选项卡 但
  • YouTube Iframe API - OnStateChange 突然不起作用[重复]

    这个问题在这里已经有答案了 直到美国东部标准时间下午 6 点左右 下面的代码都可以正常工作 但现在由于某种原因 onStateChange 没有触发 我尝试过多种浏览器 并让朋友检查过 看到什么明显错误了吗 div div div div
  • e.preventDefault 阻止点击

    我有以下代码来测试 e preventDefault 的工作原理 我认为这会阻止点击事件的发生 document ready function button click function e e preventDefault alert b
  • 运行 Terraform Plan/Apply 时出现 InvalidClientTokenID 错误

    我正在使用 Terraform 和用户数据在 AWS 中设置 HA 集群 我的 main tf 看起来像这样 provider aws access key access key secret key secret key resource
  • Node.js 抓取工具中的内存泄漏

    这是一个用 JavaScript 和 Node js 编写的简单抓取工具 用于抓取 Wikipedia 中的元素周期表元素数据 依赖项是jsdom https github com tmpvar jsdom用于 DOM 操作和链帮 http
  • jsPlumb 新连接处理程序:如何获取端点锚点位置?

    是的 所以我一直在玩 jsPlumb 假设我有一个有两个端点的 div 一个顶部中心 一个底部中心 创建新连接时 我可以使用下面的函数绑定到该事件 我的问题是 如何获得端点的锚位置 我确实获得了 Source 和 TargetEndpoin
  • 即使导出路径也找不到 conda 命令

    我将 anaconda3 安装到我的主目录中 这是我在终端中看到的 我的 bash profile 看起来像这样 导出 PATH Users spotter anaconda3 bin PATH 所以我不明白为什么 conda 不被识别 当
  • 从单个表中选择同一列两次但条件不同

    我想显示员工的姓名和号码以及老板的号码和姓名 如下所示 只有一张表 到目前为止我尝试过 SELECT ID Name Boss SELECT Name FROM Employees WHERE ID IN SELECT Boss FROM
  • 使用 pip 安装后找不到 cookiecutter 命令

    我想使用 cookiecutter 启动 django 项目 但由于某种原因找不到 cookiecutter 我所做的是 pip install cookiecutter 在那之后 cookiecutter https github com
  • C++ 支持编译时计数器吗?

    出于自省的目的 有时我想自动将序列号分配给类型或类似的东西 不幸的是 模板元编程本质上是一种函数式语言 因此缺乏实现此类计数器的全局变量或可修改状态 或者确实如此 根据请求的示例代码 include
  • 进度条的可见性

    当用户在一项活动中单击按钮时 我需要处理一些数据 因此屏幕看起来应用程序停止了 2 3 秒 这不是很多 但我想向用户提供一切正常的信息 IMO 最好的方法是进度条 仅在处理数据时才可见 我找到了ProgressBar的代码 它看起来像这样
  • 如何更改类内的变量?在Python中

    我已经开始编写一个空闲游戏的代码 但稍后我会添加某种类型的输入 我的问题是我的class库存不增加int s from def砍 我的到我的variable SP wood SP stone 它只是替换variable与它得到的号码def砍
  • 从 F# 调用 C# 异步方法会导致死锁

    我有一组 F 脚本 它们调用我们创建的各种库 其中许多库公开了最初用 C 编写的异步方法 最近我发现脚本停止工作了 我想距离我上次使用它们已经有半年了 当时它们还可以工作 我试图隔离问题并提出了以下代码来重现它 首先 我们考虑一个包含以下