c# - .NET Standard 2.0 同步获取异步HttpClient.SendAsync的Response.Content

如何以 .NET Standard 2.0 普通 synchronous 方式正确提取 HttpResponseMessage Content 属性(类型为 HttpContent),在使用异步 await HttpClient.SendAsync(request) 后获取,而不使用死锁危险任务 Result 属性或Wait() 方法?

背景:.NET Standard 2.0 C# 库使用 await HttpClient.SendAsync() 以异步方式使用一些 API,但有时它需要以普通 synchronous 方式按需提取和反序列化响应内容,即通过初始化一些 Lazy 的属性反对它。

API请求是这样的:

HttpResponseMessage response = await HttpClient.SendAsync(request).ConfigureAwait(false);

而相应的异步 Content 提取到字符串操作将是这样的:

string content = await response.Content.ReadAsStringAsync();

然后,惰性属性 (synchronous) 初始化程序将获取字符串结果,如下所示:

string result = (await response.Content.ReadAsStringAsync()).Result;

或者,有时更好:

string result = Task.Run( () => response.Content.ReadAsStringAsync() ).Result;

然而,这两种情况https://medium.com/rubrikkgroup/understanding-async-avoiding-deadlocks-e41f8f2c6f5d

挑战:库的建议解决方案是在 synchronous 调用中使用普通的 synchronous 读取,即使用 synchronous response.Content.ReadAsString() 而不是异步 response.Content.ReadAsStringAsync()

但是,这种 synchronous 方法不存在,并且没有在 .NET Standard 2.0 HttpContenthttps://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent?view=netstandard-2.0 中描述,尽管它在其他版本(即 https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent?view=net-6.0

是否可以在 .NET Standard 2.0 中以某种方式实现它,即使用 synchronous StreamReaderJsonSerializer,或任何其他安全方式以及如何实现?

提前致谢。

回答1

如何以 .NET Standard 2.0 普通 synchronous 方式正确提取 HttpResponseMessage Content 属性(类型为 HttpContent),在使用异步等待 HttpClient.SendAsync(request) 后获取,而不使用死锁危险任务 Result 属性也不是 Wait() 方法?

你有两个选择:

  1. 修复库,使其不再需要 synchronous 代码。
  2. 以不会导致死锁的方式阻止任务。

第一个选项修复了要求:

它需要以简单的 synchronous 方式按需提取和反序列化响应内容,即通过为其初始化一些 Lazy 对象的属性。

因此,如果您必须异步初始化惰性对象,请更改惰性对象以使其支持异步初始化。例如,使用我的 https://github.com/StephenCleary/AsyncEx 中的 AsyncLazy<T>,或使用 Lazy<Task<T>>

这是最好的解决方案。

另一种解决方案是https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development

API 请求是这样的……然后,惰性属性(synchronous)初始化器会获取这样的字符串结果……

完全不清楚代码将如何将 await 用于 API 请求,同时避免 await 用于读取响应内容,并保持整体 synchronous。

然而,这两种情况都可能导致死锁,具体取决于上下文。

一点也不。 Task.Run 不会死锁。 https://medium.com/rubrikkgroup/understanding-async-avoiding-deadlocks-e41f8f2c6f5d 在如何使用“死锁”术语方面相当混乱,将其与线程池耗尽混为一谈。我建议不要担心库中的线程池耗尽;如果您必须提供一个 synchronous API,那么该 API 将根据定义阻止调用线程 - 没有办法解决这个问题,因此无需担心。

相似文章

html - 启用以进行从不显示到显示的转换

目标:向上滚动时从不可见过渡到可见。问题:我检索到一些信息,这可能不是由于语法“显示”。是否有另一种解决方案来实现目标?Jsbin:https://jsbin.com/nafarabimi/edit?...

twilio - DevTools 无法加载源 map

我知道Chrome开发工具中有很多关于这些警告的帖子。对于所有这些,解决方案是关闭通知“启用javascript源maps”和“启用CSS源maps”。我想知道的是如何解决这个问题,以及导致这些警告的...

随机推荐

最新文章