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

标签 c# task .net-4.5 async-await

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

例如

  • 我拍摄了“沙漠”和“花朵”图像,并且我对它们分别进行了 4 次异步处理。
  • 然后我调用(等待)8 次 saveAsync() 方法来保存它们。

    • desert_modified 和 flower_modified、flower_modified(1)、flower_modified(2)、flower_modified(3) 都被保存了。
    • 没有图像 desert_modified(1)、desert_modified(2)、desert_modified(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);
  });

我在我的本地 PC 上将它变成了一个简单的独立测试程序,这样我就可以实际测试它了:

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

关于c# - 异步方法有时永远不会结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18138292/

相关文章:

c# - ViewManager.GetViewsOfViewModel始终返回null

c# - ILogger 未将 TRACE 和 DEBUG 消息写入目标

android - 如何为我的自定义导航配置 list 文件(任务相关性?)

c# - 将 async/await 与 DataReader 一起使用? (没有中间缓冲区!)

c# - Entity Framework 4.1 InverseProperty 属性和 ForeignKey

c# - 如何获取具有自定义属性的类的每个属性然后在下拉列表中显示它们?

c# - 'await' 有效,但调用 task.Result 挂起/死锁

c#-4.0 - 任务忽略 Thread.Sleep

c# - 常量值无法转换为 int

c# - 异步任务没有结束