可能这个问题已经有人提出了,但我一直没有找到明确的答案。假设我在 IIS 上托管了一个 Web API 2.0 应用程序。我想我明白最佳实践(防止客户端死锁)是从 GUI 事件到 HttpClient 调用始终使用异步方法。这很好而且有效。但是,如果我的客户端应用程序没有 GUI(例如窗口服务、控制台应用程序)但只有同步方法可以从中进行调用,那么最佳做法是什么?在这种情况下,我使用以下逻辑:
void MySyncMethodOnMyWindowServiceApp()
{
list = GetDataAsync().Result().ToObject<List<MyClass>>();
}
async Task<Jarray> GetDataAsync()
{
list = await Client.GetAsync(<...>).ConfigureAwait(false);
return await response.Content.ReadAsAsync<JArray>().ConfigureAwait(false);
}
但不幸的是,这可能仍然会导致死锁在随机机器上随机发生的客户端。
客户端应用程序在此时停止并且永远不会返回:
list = await Client.GetAsync(<...>).ConfigureAwait(false);
最佳答案
如果它可以在后台运行并且不强制同步,请尝试将代码(调用异步方法)包装在 Task.Run() 中。我不确定这是否会解决“死锁”问题(如果它不同步,那是另一个问题),但是如果你想从异步/等待中受益,如果你没有一直使用异步,除非您在后台线程中运行它,否则我不确定是否有好处。我有一个案例,在几个地方添加 Task.Run() (在我的例子中,从我更改为异步的 MVC Controller )并调用异步方法不仅略微提高了性能,而且提高了可靠性(不确定它是否是一个“死锁”,但看起来类似)在较重的负载下。
你会发现使用 Task.Run() 被一些人认为是一种糟糕的方法,但我真的找不到更好的方法来实现它,而且它确实看起来是一个改进。也许这是其中一种事情,其中有理想的方法来做这件事,而不是让它在你所处的不完美情况下工作的方法。:-)
[因代码请求而更新]
因此,正如其他人发布的那样,您应该“一直异步”。就我而言,我的数据不是异步的,但我的 UI 是。因此,我尽可能地进行了异步处理,然后以合理的方式使用 Task.Run 包装了我的数据调用。我认为,这就是弄清楚事情可以并行运行是否有意义的诀窍,否则,你只是在同步(如果你使用异步并立即解决它,迫使它等待答案)。我有许多可以并行执行的读取。
在上面的例子中,我认为你必须尽可能异步,然后在某个时候,确定你可以从哪里分离线程并独立于其他代码执行操作。假设您有一个保存数据的操作,但您实际上并不需要等待响应——您正在保存它,然后就完成了。您可能需要注意的唯一一件事是不要在不等待该线程/任务完成的情况下关闭程序。在您的代码中哪里有意义取决于您。
语法非常简单。我采用现有代码,将 Controller 更改为异步返回我的类的任务,该任务以前被返回。
var myTask = Task.Run(() =>
{
//...some code that can run independently.... In my case, loading data
});
// ...other code that can run at the same time as the above....
await Task.WhenAll(myTask, otherTask);
//..or...
await myTask;
//At this point, the result is available from the task
myDataValue = myTask.Result;
有关可能更好的示例,请参阅 MSDN: https://msdn.microsoft.com/en-us/library/hh195051(v=vs.110).aspx
[更新 2,与原始问题更相关]
假设您的数据读取是一种异步方法。
private async Task<MyClass> Read()
您可以调用它,保存任务,并在准备就绪时等待它:
var runTask = Read();
//... do other code that can run in parallel
await runTask;
因此,为此目的,调用异步代码,这是原始发帖人所要求的,我认为您不需要 Task.Run(),尽管我认为您不能使用“等待”,除非您这是一个异步方法——您需要 Wait 的替代语法。
诀窍在于,如果没有一些代码可以并行运行,那么它就没有什么意义了,所以考虑多线程仍然是重点。
关于c# - Web API 同步调用最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30895601/