c# - Web API 同步调用最佳实践

标签 c# iis .net-4.5 asp.net-web-api

可能这个问题已经有人提出了,但我一直没有找到明确的答案。假设我在 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/

相关文章:

c# - 在 Visual Studio 中删除匹配的大括号

c# - System.Reflection.PropertyInfo.GetValue() - 降级 .NET 版本 - 缺少方法签名

iis - 使我的 Windows Azure Web 和服务项目可用于我的局域网吗?

azure - 如何在 Azure 上设置 VMware Tanzu TAS 以部署 .Net 4.5 应用程序

c# - 自定义 ConfigurationSection 到外部 .config

c# - 使用 C# 构建的 Web 服务,用于从 mySQL 数据库中检索数据

macos - 在 IIS 上托管 Mac OS X 包 (.mpkg) 或 Bundle (.bundle)

asp.net-mvc - MVC 5 中的 VirtualPathProvider

.net - 是否有技术原因导致.NET4.0不能完全支持EF 5?

c# - 如何使用 async/await 实现命令模式