【问题标题】:Weird behavior of image图像的奇怪行为
【发布时间】:2015-08-29 08:21:59
【问题描述】:

我看到一个图像的奇怪行为。

我有两种计算热图图像的方法。 一种方法在 GUI 线程中工作,另一种在后台线程中工作。 两种方法应该相同,并且作为 png 的输出似乎很好。 GUI线程创建的图像可以加载,但从后台线程创建的图像不能。

我将计算出的图像作为文件保存在我的硬盘上,然后再次加载。 当我加载它并将其分配给图像源时,它不为空。但是当程序离开分配方法时 image.source 为空。我不明白为什么。

这是代码:

private void LoadImageClicked(object sender, RoutedEventArgs e)
{
    this.ImageHeatMap.BeginInit();
    this.ImageHeatMap.Source = new BitmapImage(new Uri(@"HeatMapImage.png", UriKind.Relative));
    this.ImageHeatMap.EndInit();
}

这就是我将图像保存为 png 的方式:

public void SaveFile(BitmapSource source, string filePath)
{
    using (var fileStream = new FileStream(filePath, FileMode.Create))
    {
        BitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(source));
        encoder.Save(fileStream);
    }
}

有趣的是我无法在调试模式下查看 Image.Source.Height 属性。但是使用工作文件我可以读取此属性。 调试如下:

英文错误消息(免费翻译):“this.Image:heatMap.Source.Height”已抛出“System.IO.IOException”类型的异常

有人可以帮助我了解问题出在哪里吗?因为我不明白为什么我无法加载图像。我可以通过 Windows 图片查看器打开它。

我认为问题出在元数据上,但我目前不知道如何解决它。

【问题讨论】:

  • GUI线程和后台线程都使用相同的保存方法?
  • 是的。但是带有 GUI 线程的那个可以工作,但背景的那个不行。我用一些技巧/解决方法修复了它,但很高兴知道为什么会有差异
  • 所以我尝试了一些方案,如果 Uri 调用的文件在程序文件夹中不存在,则只能重现您的高度、宽度、元数据错误。你试过绝对的Uri吗? Und es wär schön wenn man wüsste was dein ImageHeatMap Object bei BeginInit und EndInit macht ;)
  • Begin 和 EndInit 没有区别。您也可以将其排除在外。我只尝试过相对源
  • 您不能从除 UI 线程之外的其他线程修改 GUI 元素。您必须使用 Invoke 从另一个线程进行任何此类操作。

标签: c# multithreading image


【解决方案1】:

当涉及到 .Net 中的图像对象时,我发现需要强制处理它。使用任何操作图像的类的 .Dispose() 方法就足以释放它对文件的保留。您可能认为关闭 Stream 会强制发布此版本,但事实并非如此。

编辑:因为您不理解响应,所以您投反对票真是太糟糕了。我考虑过删除我的回复,但我认为这对社区没有好处。这是一个相关的帖子,解释了我进一步所说的内容。

Why does Image.FromFile keep a file handle open sometimes?

【讨论】:

  • 嗯,什么?我不想处理我的图像。
  • 我认为你不明白 dispose 的作用。在 Encoder.Save(...) 之后,您将调用 Encoder.Dispose() 以便将资源返回给系统并且它不会锁定文件。
  • 你不明白我的问题/问题。我知道 dispose 是做什么的,我也知道如何使用它——那么你为什么要调用 dispose 呢?使用 using 块是更好的编码。那么为什么你的解决方案应该帮助我呢?分配后我的图像为空。为什么 Dispose 应该帮助我?如果我处理它,它无论如何都是空的。感觉在哪里?
  • 当我不会通过文件打开它时,我的问题也存在。当我将图像一直保存在内存中时,问题也存在。这不会是文件句柄和/或处置的问题。你的回答对我的问题没有价值...
  • 试试这个...用这个保存图像后... "encoder.Save(fileStream);"添加另一行代码“encoder.Dispose();”该文件不会被删除,“编码器”对象将从内存中删除。由于.Net 的垃圾收集,通常你不需要做这种事情。但是,当您使用图像等时,您必须这样做。
猜你喜欢
  • 2015-02-28
  • 2012-06-16
  • 2021-06-06
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多