【发布时间】:2013-04-13 18:24:00
【问题描述】:
我在我的 WorkerRole (RoleEntryPoint) 中使用 Tasks、Async 和 await。
我有一些无法解释的循环,现在我发现如果在 await 调用中运行时间过长,角色就会循环。要重现它,只需在 Run 方法中执行 await Task.Delay(60000)。
谁能给我解释一下为什么?
【问题讨论】:
标签: azure async-await
我在我的 WorkerRole (RoleEntryPoint) 中使用 Tasks、Async 和 await。
我有一些无法解释的循环,现在我发现如果在 await 调用中运行时间过长,角色就会循环。要重现它,只需在 Run 方法中执行 await Task.Delay(60000)。
谁能给我解释一下为什么?
【问题讨论】:
标签: azure async-await
Run 方法必须 阻塞。来自the docs:
如果您确实覆盖了 Run 方法,您的代码应该会无限期地阻塞。如果 Run 方法返回,则通过引发 Stopping 事件并调用 OnStop 方法自动回收角色,以便在角色脱机之前执行您的关闭序列。
一个简单的解决方案就是这样做:
public override void Run()
{
RunAsync().Wait();
}
public async Task RunAsync()
{
while (true)
{
await Task.Delay(60000);
}
}
或者,您可以使用AsyncContext from my AsyncEx library:
public override void Run()
{
AsyncContext.Run(async () =>
{
while (true)
{
await Task.Delay(60000);
}
});
}
无论您选择哪个选项,Run 都应该不是async。这有点像控制台应用程序的Main (see my blog for why async Main is not allowed)。
【讨论】:
async Main。出于同样的原因,不允许使用 async Run。我的示例将在 60 秒后回收,因为它从 Run 返回。如果您不想回收,请不要从Run返回。
我建议Task.Delay 使用较低的值,例如 1000 (ms)。我怀疑工人角色无法对健康检查做出足够快的反应。然后该角色被视为无响应并重新启动。
确保Run 方法永远不会返回类似这样的内容
while (true)
{
Thread.Sleep(1000);
}
或者在你的情况下使用Task.Delay。
【讨论】: