【发布时间】:2014-06-20 02:59:54
【问题描述】:
我正在一个简单的小控制台应用程序中使用 C# 中的 async 和 await。我的目标很简单:以异步方式处理文件列表,以便处理一个文件不会阻塞其他文件的处理。没有一个文件是相互依赖的,并且有(比方说)数千个文件要经过。
这是我目前拥有的代码。
public class MyClass
{
public void Go()
{
string[] fileSystemEntries = Directory.GetFileSystemEntries(@"Path\To\Files");
Console.WriteLine("Starting to read from files!");
foreach (var filePath in fileSystemEntries.OrderBy(s => s))
{
Task task = new Task(() => DoStuff(filePath));
task.Start();
task.Wait();
}
}
private async void DoStuff(string filePath)
{
await Task.Run(() =>
{
Thread.Sleep(1000);
string fileName = Path.GetFileName(filePath);
string firstLineOfFile = File.ReadLines(filePath).First();
Console.WriteLine("{0}: {1}", fileName, firstLineOfFile);
});
}
}
而我的Main() 方法只是调用这个类:
public static class Program
{
public static void Main()
{
var myClass = new MyClass();
myClass.Go();
}
}
我似乎遗漏了这个异步编程模式的某些部分,因为每当我运行程序时,实际处理的文件数量似乎是随机的,从一个都没有到全部六个(在我的示例文件集)。
基本上,主线程不会等待所有文件都被处理,我认为这是异步运行的一部分,但我不太希望这样。我想要的是:在尽可能多的线程中处理尽可能多的这些文件,但在完成之前仍然等待它们全部完成处理。
【问题讨论】:
-
您开始并等待 foreach 循环中的每个任务...创建一个任务数组并使用 WaitAll。
-
这段代码存在一些概念性问题,但主要的技术问题是:
new Task(() => DoStuff(filePath)),其中DoStuff是async void方法。您在这里进行了一次即发即弃的调用,任务在DoStuff方法完成之前完成,myClass.Go()也是如此。 -
并行处理项目是一个非常基本的并发主题。事实上,据我所知,您的问题是关于最基本的情况。如果你朝那个方向做一些研究,那可能是最好的。您会很快找到解决方案。
-
@Scott 是的,自从引入了 async/await 的东西以来,这些概念就变得模棱两可并且误导了初学者。我看到 async/await 一直在使用,而同步线程本来可以更简单并完成同样的事情。
-
这个问题现在已经足够清晰,可以与现有材料共存。如果您愿意,请添加到您现有的答案中。关键是这个问题对未来的访问者更有用。接受您认为对他人最有帮助的答案。
标签: c# multithreading asynchronous async-await