我已经完成了一些工作,但是在示例异步方法方面没有找到太多方法,这些异步方法既不复杂也不简单。
我一直在努力提高应用程序的效率,并且我确信我不需要实现自己的线程。基本上,此代码来自已经具有异步调用的应用程序,该异步调用使用Cookie Aware Web客户端代码登录到HTTPS站点,获取cookie,使用身份验证cookie枚举特定页面,然后下载特定文件。所述特定文件是“zip”格式,扩展名为“.bfp”。下面这段代码用于提取zip文件(从100多个源IP中下载到文件夹结构中的数万个)。
我的问题是应用程序通过使用此异步设置解析文件的一部分冻结,但偶尔会完成。有时它会挂起并且只是坐在那里,有时它会崩溃并弹出Windows错误报告。
作为一个说明,我有一个BS CIS学位,但我不是一个日常工作的程序员。我是系统工程师/架构师(我也有BS和MS)。我没有人在这里反弹任何有任何编程经验的代码。我对从MS和Google的Channel9视频中学到的async / await库的了解。如果这个实现看起来很糟糕,它可能是,而且我并不声称自己是专家,尤其是异步。我遗漏了应用程序运行正常的其他部分的大部分代码,因为它有我不想分享的信息,而且与问题/问题无关。
private async void ParseZipFiles()
{
await UpdateMain("Started Parsing Compressed Log Files." + Environment.NewLine);
FileInfo[] diZip = new DirectoryInfo(@"C:\LogFiles\ZipFiles\").GetFiles("*.bfp",SearchOption.AllDirectories);
await Task.WhenAll(diZip.Select(async s => await Task.Run(async () => await ParseLogFile(s.FullName))));
await UpdateMain("Finished Parsing Compressed Log Files." + Environment.NewLine);
}
private async Task ParseZipFile(string filename)
{
try
{
using (ZipArchive bfpFile = await Task.Run(async () => new ZipArchive((Stream)new FileStream(filename, FileMode.Open))))
{
await Task.WhenAll(bfpFile.Entries.Select(async s => await Task.Run(async () =>
{
if (s.FullName.EndsWith(".log", StringComparison.OrdinalIgnoreCase) && s.Name.Split('.').First().All(char.IsDigit) == true && s.Name.Split('.').Count() == 2)
{
string extractPath = Path.Combine(@"C:\LogFiles\Extracted\" + filename.Split('\\')[3].ToString() + @"\", s.Name);
await Task.Run(async () => await Task.Run(() => s.ExtractToFile(extractPath, true)));
}
})));
}
}
catch
{
await UpdateMain("Compressed archive: " + filename + " is corrupted. Probably on the source system." + Environment.NewLine);
}
}
答案 0 :(得分:0)
之前我使用过Task.WhenAll(),我想你想用它来简化任何一行。你有更多的等待语句,而Task.Run将在一个新的线程中启动。由于您构建await语句的方式,您可能正在创建无法完成任务的条件。那么为什么每个拉链都没有一个线程?
using (ZipArchive bfpFile = new ZipArchive(new FileStream(filename,
FileMode.Open))) {
await Task.WhenAll(bfpFile.Entries.Select(s => Task.Run(() =>
{
if (s.FullName.EndsWith(".log", StringComparison.OrdinalIgnoreCase) && s.Name.Split('.').First().All(char.IsDigit) == true && s.Name.Split('.').Count() == 2)
{
string extractPath = Path.Combine(@"C:\LogFiles\Extracted\" + filename.Split('\\')[3].ToString() + @"\", s.Name);
s.ExtractToFile(extractPath, true)));
}
}
)));
}
另外,更改此行代码
await Task.WhenAll(diZip.Select(s => Task.Run(() =>
ParseLogFile(s.FullName))));
最终不确定该行是否意味着调用ParseZipFile()而不是ParseLogFile(),但是你有代码而我没有。