【发布时间】:2019-08-07 21:47:53
【问题描述】:
我的 REST API 服务器中有以下内容(使用 OWIN):
[ResponseType(typeof(Session))]
[Route("api/v1/async")]
public Session async_status()
{
AsyncStatus();
return new Session() {...};
}
private async Task<int> AsyncStatus()
{
await SyncMethod();
return 42;
}
private Task<int> SyncMethod()
{
CopyFileThatTakesALongTime(....);
// OR
Thread.Sleep(60000);
return Task.FromResult(42);
}
为什么死掉它会阻塞并且客户端没有获得所需的异步性。我希望在调用时:
await SyncMethod();
调用者将被释放并解除阻塞,而其余的睡眠将被执行。我错过了什么?
P.S:我可以通过替换它来轻松修复它:
AsyncStatus();
与:
Task.Run(() => AsyncStatus() );
我不这样做的原因是因为阅读:
https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-using.html
换句话说,如果像上面文章中那样在 Web 服务器中使用 Task.Run() 很糟糕,但是您不能使用 async/await,那么解决方案是什么?
【问题讨论】:
-
您是否试图模拟从异步代码调用某些阻塞 API?首先,异步应该传播到调用堆栈的顶部(因此您应该将控制器的公共方法标记为异步并在异步调用上执行等待)。其次,应不惜一切代价避免使用 Thread.Sleep。在异步世界中,它被“await Task.Delay(...)”取代
-
似乎您正在尝试“解雇并忘记”。阅读this。
-
一切都是票价 Api 控制器是公开的
-
不确定你想用这段代码完成什么。看起来您正在将任务(协程)的概念与线程混合在一起。这是软件中多任务处理的两种截然不同的方法。使用 await Task.Delay(...) 会将 SyncMethod 修复为异步兼容(但我不会将其称为同步方法)。最后, async_status() 方法会触发并忘记,因此无论如何都不会在该方法中挂起。您能否为您要完成的工作提供更多背景信息?
-
我想要完成的非常简单。让我们举一个真实的例子。假设您想开发一个 API 来指示服务器将大文件从位置 A 复制到 B。您不希望调用被阻塞,而只是触发副本,仅此而已。另一个要求之一是事后能够知道副本的进度,但我们暂时不处理这部分。
标签: c# asp.net async-await