Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从同步方法调用异步方法是ASP.NETWebAPI-问题_C#_Asp.net_.net_Asynchronous_Asp.net Web Api2 - Fatal编程技术网

C# 从同步方法调用异步方法是ASP.NETWebAPI-问题

C# 从同步方法调用异步方法是ASP.NETWebAPI-问题,c#,asp.net,.net,asynchronous,asp.net-web-api2,C#,Asp.net,.net,Asynchronous,Asp.net Web Api2,我有一个ASP.NETWebAPI2应用程序,我试图从sync方法调用asnyc方法,同时遇到了一些问题。如果我只是作为常规方法调用该方法,则延迟后的主体不会被执行,如果我使用Task.Run()调用它,则会被执行 public void CallingMethod(MethodExecutionArgs args) { //do something with the args System.Diagnostics.Debug.WriteLine("BEFO

我有一个ASP.NETWebAPI2应用程序,我试图从sync方法调用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");

}

专用异步任务WriteFileToDiskAsync(动态文件)
{
System.Diagnostics.Debug.WriteLine(“异步内延迟之前”);
等待任务。延迟(3000);
System.Diagnostics.Debug.WriteLine(“WriteFile()-延迟后”);
}
结果:我总是看到从
CallingMethod
写入的行,但是当我像常规方法一样调用异步方法时,我只看到“在异步内部延迟之前”,如果我使用Task.Run()调用它,它会看到异步方法中的两行

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

我读了这些文章,但不明白为什么会发生这种情况:

  • 根据大多数文章,不建议我尝试做什么(除其他外,异步方法的异常会被吞没),但在我的情况下,我已经拥有生成响应所需的信息,并且异步方法中所做的与客户机无关
上下文:我试图实现的是,在创建
X资源
(将其保存在数据库中)的现有API路由上,在创建X资源后,我希望异步调用一个方法,该方法将使用该X资源中的一些信息创建json文件,并将其保存在文件系统中。但是,即使文件写入失败,我也希望向客户机返回一个成功的响应(因为他的请求实际上是保存成功的
X资源
),他不关心在XYZ文件系统中创建外部文件

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

问题1:有人能解释这种行为吗?为什么异步方法不能完全执行?这是否与Stephen Cleary所说的有关:如果您出于任何原因丢失了AppDomain,则正在进行的工作将丢失

否。在本例中,AppDomain仍然存在。在ASP.NET(预核心)中,有一个ASP.NET
SynchronizationContext
表示请求

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

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


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

最好的解决方案是:不要从非
async
方法调用
async
方法。是什么阻止了您将
调用方法
标记为
异步
并让它返回任务?因为调用
调用方法
的方法是同步的,它被N个方法调用的60多个不同方法调用。。。如果我只是使CallingMethod异步,并定期从同步方法调用它,我会得到与上面描述的相同的行为,我肯定会在单独的进程中运行,可能会先将其发送到队列,这样您就可以完全控制文件创建的过程。@guxxo是这样吗?做一次重构,使它们也是异步的。你会发现,正确使用async意味着
async
会在整个应用程序中增长。重构应用程序并不难。只需确保等待所有异步调用,并且它们是从标记为async的方法调用的,并返回一个或多个任务。在大多数情况下,这是一个直截了当的重构。很难想象一个开发人员要花一天以上的时间来完成这项工作。这是一个直接的重复重构。你做一次,然后一遍又一遍重复同样的过程。
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");
}