我有一些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);
}
}
调用者是主要方法。 当我通过以下两种方式运行任务时,这些任务运行良好并产生了正确的结果:
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
'完成'时,可能会捕获一个新的线程池线程以执行循环的下一步,...,循环将始终在{{1}处的其他线程中运行}。
在方式2中,当await
立即执行时,可能会使用新的线程池线程,循环总是在开始时在其他线程中运行。
结果相同,差异在哪里?
所以我的问题不是关于Task.Run与async-await!
答案 0 :(得分:1)
异步代码允许当前线程被释放以执行其他工作,同时等待其他响应。但是第一个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);
}