我希望这里有一个简单的答案,这可能是由于我对异步操作的误解......
我有一个方法可以手动启动,也可以在程序加载时自动启动。当手动调用时(按下按钮),异步方法可以正常工作。然而,当自动加载时,该方法似乎跳过主要的"等待"方法的一部分,不进行任何工作,直接跳到最后。
整个过程从这个方法开始:
private void StartBatch()
{
var batchSize = (int)BatchSizeSlider.Value;
if (_config.AutoStart)
{
ExecutionLogAddItem(string.Format("Auto batch processing started (batch size: {0})", batchSize.ToString()));
Task.Factory.StartNew(async () =>
{
await BatchTransfer(batchSize);
CompleteBatch();
});
}
else
{
var start = ConfirmStartBatch();
var doBatch = start.ContinueWith(async (continuation) =>
{
//start task
if (start.Result == true)
{
ExecutionLogAddItem("Batch processing started.");
ExecutionLogAddItem(string.Format("Batch size set at {0}", batchSize.ToString()));
await BatchTransfer(batchSize).ContinueWith((x) => CompleteBatch());
}
else
{
ExecutionLogAddItem("Batch processing aborted.");
}
});
}
}
如果_config.AutoStart
为真,则BatchTransfer方法似乎无法执行任何操作,而是直接跳转到CompleteBatch()
方法。如果手动调用,一切都按预期工作。
奇怪的是,如果我在自动启动方法中在await BatchTransfer(batchSize)
上设置断点,我可以单步执行代码并进行批量传输。因此,当调试它工作时,如果没有调试它不会。请帮忙!
答案 0 :(得分:5)
这是因为 -
Task.Factory.StartNew(async () =>
{
await BatchTransfer(batchSize);
CompleteBatch();
});
您正在等待内部任务完成await
,但Task.Factory.StartNew(async () =>
本身是异步任务,不等待。您还应该等待Task.Factory.StartNew(async () =>
这样 -
await Task.Factory.StartNew(async () =>
当你正在调试时,保持调用内部任务的单独线程并且你可以看到执行但是当正常运行时后台仍然有效,但你没有看到它,因为你没有等待{{1 }}
如果检查线程池和线程ID,我相信在调试时你会发现它们是不同的。
此博客可能会帮助您了解情况 - http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
答案 1 :(得分:1)
要使用await
,您必须制作方法async
并在没有Task.Factory.StartNew
的情况下调用它。还有一件事,而不是void
使得返回类型为您方法的Task
,因为void async是fire and forget。你无法跟踪它们。
private async Task StartBatch()
{
await BatchTransfer(batchSize);
CompleteBatch();
}
检查此链接。它有async
的基本演示,对于理解asynchrony
的工作原理非常有帮助。 Six Essential Tips For Async - Introduction。它包括六个非常必要的提示。我建议您浏览所有这些内容,但要了解当前的问题情况,您可以通过提示1,标题为 Async void仅适用于顶级事件处理程序。