异步方法有时永远不会结束

本文关键字:结束 永远 时永 异步方法 | 更新日期: 2023-09-27 18:26:53

我正在拍摄图像并对其进行处理。然后我尝试将位图(这些图像)保存在一个文件中。

例如

  • 我拍摄了"沙漠"answers"花朵"的图像,并对它们进行了4次异步处理
  • 然后我调用(wait)8次saveAsync()方法来保存它们。

    • 所发生的是desert_modified和flower_modified,flower_modified(1),flower_modified(2),flower_modified(3)被保存
    • 没有图像desert_modified(1)、desert_mModified(2)和desert_mmodified(3)

拯救他们的方法永远不会结束。有什么建议吗?

async private Task saveAsync(Bitmap bitmap, String path, String fileName, int requestNo)
{
    int temp = 1;
    String pth = path;
    String fileName1 = fileName;
    try
    {
        await Task.Run(() =>
            {
                if (File.Exists(pth))
                {
                    String[] array = fileName1.Split('.');
                    String modifiedFileName = array[0] + "_modified" + "(" + temp + ")." + array[1];
                    pth = fullPath.Replace(fileName1, modifiedFileName);
                    while (File.Exists(pth))
                    {
                        temp++;
                        //array = fileName.Split('.');
                        modifiedFileName = array[0] + "_modified" + "(" + temp + ")." + array[1];
                        pth = fullPath.Replace(fileName1, modifiedFileName);
                    }
                    bitmap.Save(@pth);
                }
                else
                {
                    bitmap.Save(@pth);
                }
                bitmap.Dispose();
            });
    }
    catch (Exception ex)
    {
        outputTextBox2.Text += ex.InnerException.Message;
    }
}

异步方法有时永远不会结束

如果您有兴趣改进代码,如我在评论中所暗示的,这里有一个开始:

正如你所看到的,这个

  • 删除(名称混乱)局部变量,如pthfileName1modifiedFileName
  • 不再滥用Split(错误地)解析路径(如果目录有扩展名怎么办?如果文件名包含.本身怎么办?)
  • 使用PathCombine获取正确的路径分隔符
  • 使用固定格式字符串轻松生成候选文件名
  • 使用单个do-while循环,而不是复制生成文件名的行

总的来说,我认为这是一个很多简单。

await Task.Run(() =>
  {
      var fmt = Path.Combine(path, Path.GetFileNameWithoutExtension(fileName)) + "_modified{0}" + Path.GetExtension(fileName);
      int counter = 1;
      string newName;
      do {
          newName = string.Format(fmt, counter++);
      }
      while (File.Exists(newName));
      using (bitmap)
          bitmap.Save(newName);
  });

我在本地电脑上把它做成了一个简单的独立测试程序,这样我就可以真正测试它了:

using System.IO;
using System;
public class X
{
    public class Bitmap : IDisposable { 
        public void Dispose() { } 
        public void Save(string location)
        {
            Console.WriteLine("Saving: {0}", location);
            using (var s = new StreamWriter(location))
                s.WriteLine("hello world");
        }
    }
    private static void saveAsync(Bitmap bitmap, String path, String fileName, int requestNo)
    {
        Action a = () =>
          {
              var fmt = Path.Combine(path, Path.GetFileNameWithoutExtension(fileName)) + "_modified{0}" + Path.GetExtension(fileName);
              int counter = 1;
              string newName;
              do {
                  newName = string.Format(fmt, counter++);
              }
              while (File.Exists(newName));
              using (bitmap)
                  bitmap.Save(newName);
          };
        a();
        a();
        a();
        a();
    }
    public static void Main()
    {
        saveAsync(new Bitmap(), "/tmp", "foo.png", 3);
    }
}

这将打印

Saving: /tmp/foo_modified1.png
Saving: /tmp/foo_modified2.png
Saving: /tmp/foo_modified3.png
Saving: /tmp/foo_modified4.png

您使用String.Replace,这在这里实际上是不合适的。我认为您的代码中的主要错误是,您试图在while循环中替换pth中的fileName1尽管fileName1在pth中没有出现,因为它在while环路之前被修改了因此pth在while循环中从未更改,这就是while循环从未结束的原因。

要解决此问题,请使用pth = fullPath.Replace(pth, modifiedFileName),我建议使用pth = modifiedFileName

无论如何,使用Replace不会节省任何内存,因为C#和许多其他语言中的字符串都是不可变的!因此,即使通过Replace,也会生成一个新的String。

编辑:。。。嗯。也许这个答案不是完全正确的,因为你正在处理fullPath,但另一方面,fullPath没有在这个函数中定义:)。。这是从哪里来的?