spo*_*ker 5 c# asynchronous async-await
我在“正确的方法”周围使用了引号,因为我已经清楚地知道使用异步API的正确方法是简单地让异步行为在整个调用链中传播。这里不是一个选择。
我正在处理一个非常大而复杂的系统,该系统专门设计用于在循环中同步进行批处理。
我突然使用HttpClient的原因是因为在此之前,用于批处理的所有数据都是从SQL数据库中收集的,而现在我们将Web API调用添加到了混合中。
是的,我们正在同步执行循环中调用Web API。我知道。重写整个事情是异步的不是一个选择。这实际上是我们想要做的。(我们正在尽可能减少API调用的次数)
实际上,我确实尝试在调用链上传播异步行为,但是后来我发现自己有50个文件有很深的变化,仍然有数百个编译器错误需要解决,并失去了所有希望。我被打败了。
因此,回到问题所在,考虑到Microsoft的建议,从不使用WebRequest进行新开发,而改用HttpClient(仅提供异步API),我该怎么办?
这是我在做什么的伪代码...
foreach (var thingToProcess in thingsToProcess)
{
thingToProcess.ProcessStuff(); // This makes an API call
}
Run Code Online (Sandbox Code Playgroud)
如何实现ProcessStuff()?
我的第一个实现看起来像这样
public void ProcessStuff()
{
var apiResponse = myHttpClient // this is an instance of HttpClient
.GetAsync(someUrl)
.Result;
// do some stuff with the apiResponse
}
Run Code Online (Sandbox Code Playgroud)
但是,我被告知,由于同步上下文而从ASP.NET之类的方法调用.Result时,以这种方式调用它可能导致死锁。
猜猜是什么,该批处理过程将从ASP.NET控制器开始。是的,再次,我知道,这很愚蠢。从ASP.NET运行时,它仅是“批处理”一项,而不是整个批处理,但是我离题了,它仍然从ASP.NET调用,因此我担心死锁。
那么解决这个问题的“正确方法”是什么?
ale*_*exs 16
对于现在遇到此问题的任何人,.NET 5.0 已将同步Send方法添加到HttpClient. https://github.com/dotnet/runtime/pull/34948
因此,您可以使用 this 而不是SendAsync。例如
public string GetValue()
{
var client = new HttpClient();
var webRequest = new HttpRequestMessage(HttpMethod.Post, "http://your-api.com")
{
Content = new StringContent("{ 'some': 'value' }", Encoding.UTF8, "application/json")
};
var response = client.Send(webRequest);
using var reader = new StreamReader(response.Content.ReadAsStream());
return reader.ReadToEnd();
}
Run Code Online (Sandbox Code Playgroud)
这段代码只是一个简化的例子,它不是生产就绪的。
kam*_*eet 12
尝试以下-
var task = Task.Run(() => myHttpClient.GetAsync(someUrl));
task.Wait();
var response = task.Result;
Run Code Online (Sandbox Code Playgroud)
仅在无法使用异步方法时才使用它。
如msdn博客-https : //blogs.msdn.microsoft.com/jpsanders/2017/08/28/asp-net-do-not-use-task-result-in-main-所述,此方法完全没有死锁 上下文/
| 归档时间: |
|
| 查看次数: |
3361 次 |
| 最近记录: |