多任务运行与不等待异步方法?



我有一些IO绑定作业(定期将一些数据写入文件(代码如下:

public async Task SaveToFile1(int sleepTimeout)
{
while (true)
{
// Do file saving work
await Task.Delay(sleepTimeout).ConfigureAwait(false);
}
}
public async Task SaveToFile2(int sleepTimeout)
{
while (true)
{
// Do file saving work
await Task.Delay(sleepTimeout).ConfigureAwait(false);
}
}
public async Task SaveToFile3(int sleepTimeout)
{
while (true)
{
// Do file saving work
await Task.Delay(sleepTimeout).ConfigureAwait(false);
}
}

调用方是主方法。 当我使用2种方式运行时,这些任务运行良好并产生了正确的结果,如下所示:

void main () 
{
// other codes
// way 1:
SaveToFile1(1000);
SaveToFile2(1000);
SaveToFile3(1000);
// other codes will not let the app exit
}
void main () 
{
// other codes
// way 2:
Task.Run(async() => await SaveToFile1(1000));
Task.Run(async() => await SaveToFile2(1000));
Task.Run(async() => await SaveToFile3(1000));
// other codes will not let the app exit
}

哪种方式是正确的,或者另一种方式是适合我的情况的最佳选择?

感谢您的回答!


编辑:

在方式 1 中,当await Task.Delay"完成"时,可能会捕获一个新的线程池线程来执行循环的下一步,...,循环将始终在命中await在其他线程中运行。

在方式2中,可能会使用一个新的线程池线程,当Task.Run立即执行时,循环将始终在开始时在其他线程中运行。

结果是一样的,差异在哪里?

所以我的问题不是关于Task.Run vs async-await!

异步代码允许释放当前线程以执行其他工作,同时等待来自其他内容的响应。但是,第一个await之前的所有代码都将在您调用它的同一线程上完成。如果该代码占用大量 CPU,则可能会很明显。

如果不使用Task.Run,该方法将在同一线程上运行,直到第一个异步 I/O 请求,届时它将返回一个Task,并且将调用下一个方法。

Task.Run将在不同的线程上执行代码。如果它确实执行了一些 CPU 密集型工作,并且您不希望在当前线程上完成(例如在桌面应用程序中,您不希望在 UI 线程上完成(,则这很好。但是启动一个新线程的成本也很小。

使用Task.Run是否会产生任何明显的差异取决于您正在编写的应用程序类型和您的方法的作用。

如果你不立即等待他们,那很好,但如果你不等待他们,那么你永远不会知道他们什么时候完成,他们是否成功完成,或者抛出和异常。这称为"即发即弃"。只有当你不在乎他们是否成功时,才这样做。

相反,您可以在最后等待以确保它们成功完成。例如:

void main () 
{
// other codes
var taskList = new List<Task>();
taskList.Add(SaveToFile1(1000));
taskList.Add(SaveToFile2(1000));
taskList.Add(SaveToFile3(1000));
// other codes will not let the app exit
// wait till everything finishes before exiting
await Task.WhenAll(taskList);
}

最新更新