C# C异步Zip文件提取

C# C异步Zip文件提取,c#,asynchronous,async-await,zip,zipfile,C#,Asynchronous,Async Await,Zip,Zipfile,我已经做了一些研究,但是没有发现太多的异步方法示例,它们既不是非常复杂,也不是非常简单 我一直在努力提高应用程序的效率,并且确信我不需要实现自己的线程。基本上,这段代码来自一个应用程序,该应用程序已经具有运行异步调用,该调用使用Cookie感知的Web客户端代码登录HTTPS站点,获取Cookie,使用身份验证Cookie枚举特定页面,然后下载特定文件。所述特定文件为zip格式,扩展名为.bfp。下面这段代码用于提取zip文件。有成千上万的zip文件从100多个源IP下载到文件夹结构中 我的问题

我已经做了一些研究,但是没有发现太多的异步方法示例,它们既不是非常复杂,也不是非常简单

我一直在努力提高应用程序的效率,并且确信我不需要实现自己的线程。基本上,这段代码来自一个应用程序,该应用程序已经具有运行异步调用,该调用使用Cookie感知的Web客户端代码登录HTTPS站点,获取Cookie,使用身份验证Cookie枚举特定页面,然后下载特定文件。所述特定文件为zip格式,扩展名为.bfp。下面这段代码用于提取zip文件。有成千上万的zip文件从100多个源IP下载到文件夹结构中

我的问题是,应用程序通过使用此异步设置解析文件而冻结了一部分,但偶尔会停止。有时它挂起,只是坐在那里,其他时候它崩溃,Windows错误报告弹出

值得注意的是,我有一个BS CIS学位,但我不是日常工作中的程序员。我是一名系统工程师/架构师,在这方面我也有学士和硕士学位。我这里没有一个有任何编程经验的人能把我的代码弹出来。我从微软和谷歌的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);
    }
}

我以前用过Task.whalll,我想你想用它来简化任何一行。您的等待语句比需要的多得多,Task.Run将在新线程中启动。很可能你正在创造条件,因为你构建等待语句的方式,什么都没有完成。那么为什么不每个拉链一根线呢

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,但你有代码,我没有。

嗨,凯文,谢谢你的解释。这一行是正确的,我有一个由按钮按下事件调用的方法,然后枚举文件,然后调用该方法进行提取。我使用的是同步程序,这是我第一次尝试异步。我来简化一下,看看会发生什么。好吧,我想这行还是应该简化为我键入的内容。祝你好运-没关系,我明白你的意思了,那句话错了。一定是那天太晚了,我的咖啡因流中有太多的血。