【问题标题】:Adding asynchronous concurrency to replace foreach loop C#添加异步并发以替换 foreach 循环 C#
【发布时间】:2021-01-29 06:42:44
【问题描述】:

我有一个创建 Zip 文件的函数,当文件数为几千时它工作得很好。但是,这在有时间限制的操作中并不是一个有效的解决方案。我想知道是否可以添加异步并发,以便最大限度地减少完成操作所需的总时间。

代码:

public static void CreateZip()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    string dirRoot = @"C:\Dir\";

    //get a list of files
    string[] filesToZip = Directory.GetFiles(dirRoot, "*.*",
        SearchOption.AllDirectories);

    string zipFileName = @"C:\Dir.zip";

    using (MemoryStream zipMS = new MemoryStream())
    {
        using (ZipArchive zipArchive = new ZipArchive(zipMS, ZipArchiveMode.Create,
            true))
        {

            //loop through files to add
            foreach (string fileToZip in filesToZip)
            {
                //read the file bytes
                byte[] fileToZipBytes = System.IO.File.ReadAllBytes(fileToZip);

                //create the entry - this is the zipped filename
                //change slashes - now it's VALID
                ZipArchiveEntry zipFileEntry = zipArchive.CreateEntry(
                    fileToZip.Replace(dirRoot, "").Replace('\\', '/'));

                //add the file contents
                using (Stream zipEntryStream = zipFileEntry.Open())
                using (BinaryWriter zipFileBinary = new BinaryWriter(zipEntryStream))
                {
                    zipFileBinary.Write(fileToZipBytes);
                }
            }
        }

        using (FileStream finalZipFileStream = new FileStream(zipFileName,
            FileMode.Create))
        {
            zipMS.Seek(0, SeekOrigin.Begin);
            zipMS.CopyTo(finalZipFileStream);
        }
        stopwatch.Stop();
        Console.WriteLine("Total time elapsed: {0}",
            stopwatch.ElapsedMilliseconds / 1000);
    }
}

【问题讨论】:

  • 什么样的应用程序?
  • 为什么要先将 zip-archive 写入内存流,然后再写入实际文件?

标签: c# asynchronous async-await


【解决方案1】:

我没有提到zipArchive 上的任何方法都是线程安全的。因此应该假设它们不是,并且你不能从多个线程调用它而不发生坏事。

您可以在后台线程上将整个方法作为任务运行,从而不会阻塞主线程,请参阅asynchronous programmingTask.Run。向用户显示进度条通常也很好。但这不会使实际压缩时间更快。

还有其他压缩库,我知道7zip支持多线程压缩,但可能还有其他的。

另外,如果您只想从目录创建存档,您可能需要使用CreateFromDirectory

您可以在创建条目时选择压缩级别,以在速度和大小之间进行权衡。 SharpZipLib 可能会提供更多的灵活性。但是这样能做的也就这么多了,压缩文件涉及到大量的IO操作,这根本上是很慢的。

【讨论】:

  • 你的意思是这样的吗:Task tasks = Task.Factory.StartNew(() => { CreateZip() });
  • @aniruddha 这是一种方法。
  • 还有什么方法可以加快这个过程?
  • @aniruddha Task.Factory.StartNew... 等同于 Task.Run(CreateZip),但两者都没有提供任何加速,只是 UI 保持响应。
  • 谢谢!这是一个控制台应用程序。我需要找到一个解决方案来加快进程
猜你喜欢
  • 1970-01-01
  • 2020-02-18
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 2018-08-20
相关资源
最近更新 更多