c# - 从同步方法调用异步方法是 ASP .NET web api - 问题

标签 c# asp.net .net asynchronous asp.net-web-api2

我有一个 ASP .NET web api 2 应用程序,我试图从同步方法调用 asnyc 方法,同时我遇到了一些问题。如果我只是将方法作为常规方法调用,延迟后的主体不会被执行,如果我使用 Task.Run() 调用它,它会被执行

public void CallingMethod(MethodExecutionArgs args)
{
  //do something with the args
            System.Diagnostics.Debug.WriteLine("BEFORE ");

            WriteFileToDiskAsync(args); // If I run only this, I never see "WriteFile() - AFTER delay" in the output
            Task.Run(async () => await WriteFileToDiskAsync(args)); // this executes the entire async method
            System.Diagnostics.Debug.WriteLine($"Finally written from sync method");

}

private async Task<bool> WriteFileToDiskAsync(dynamic file)
{
            System.Diagnostics.Debug.WriteLine("Before delay inside async");
            await Task.Delay(3000);
            System.Diagnostics.Debug.WriteLine("WriteFile() - AFTER delay");
}

结果:我总是看到从 CallingMethod 写的行,但是当我像常规方法一样调用异步方法时,我只看到 “Before delay inside async” ,如果我用 Task.Run() 调用它,它会看到来自异步方法的两行。

问题 1: 谁能解释一下这种行为,为什么异步方法没有完全执行? 这是否与 Stephen Cleary 所说的有关:如果您出于任何原因丢失了 AppDomain,那么正在进行的工作也会丢失。

我阅读了这些文章,但无法弄清楚为什么会这样:

上下文:我想要实现的是,在创建 X 资源(将其保存在数据库中)的现有 API 路由上,创建 X 资源后,我想异步调用一个方法,该方法将使用来自该 X 资源的一些信息创建一个 json 文件并将其保存在文件系统中。但是即使文件写入失败,我想向客户端返回一个成功的响应(因为他的请求是实际保存 X Resource - 成功了)他不关心创建外部XYZ 文件系统中的文件。

问题 2:考虑到 CreateResource 路由中链接的所有现有方法都是同步的,您认为实现上述目标的最佳实践是什么?

最佳答案

Question1: Can someone explain this behavior, why doesn't the async method execute fully? Does it have something to do with what Stephen Cleary says: If you lose your AppDomain for any reason, that in-progress work is lost.

没有。在这种情况下,AppDomain 仍然存在。在 ASP.NET(pre-Core)中,有一个 ASP.NET SynchronizationContext 表示请求。 await by default captures the current context and uses that to resume executing its async method .

因此,当 await 完成时,它会尝试在该请求的 SynchronizationContext 上恢复执行。但是,该请求已经完成,因此在该上下文中恢复没有意义。产生的行为是未定义的。

Question2: What would you say is the best practice to achieve what I described above, considering all the existing methods chained in the CreateResource route are sync?

如果您确定要提前返回,那么您应该有一个创建文件的后台服务句柄,而不是 ASP.NET 服务。由于您已经有一个数据库,您可以使用发件箱模式,将消息放在“发件箱”表中,作为与资源创建相同的事务的一部分。然后一个单独的后台服务读取“发件箱”表并写入 JSON 文件。

关于c# - 从同步方法调用异步方法是 ASP .NET web api - 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64611090/

相关文章:

c# - ML.NET 算法评估有关乳腺癌的实例总是错误的

c# - 如何使用 Mvc 3 Razor 填充列表?

这个 C 哈希函数的 C# 等价物

javascript - 将“”等特殊 HTML 字符代码转换为普通字符

javascript - 构建网站时,我应该在特定用户控件还是母版页中引用 javascript 库?

c# - 是否可以在 Windows 上使用 .NET 完全接管多个屏幕中的一个屏幕?

c# - onmouseover 效果在 asp.net imagebutton 中不起作用

c# - 在 C# 中,我如何知道赋值运算符 (=) 何时会复制值或内存地址(引用)?

c# - 有没有办法从代码隐藏中读取 System.Web.Optimization 内容?

C# 编码(marshal)处理 - 获取 C char** 的内容并转换为 byte[]