【问题标题】:Cannot delete file used by some other process无法删除其他进程使用的文件
【发布时间】:2012-10-09 12:21:00
【问题描述】:

我正在使用以下代码在我的 wpf 应用程序中显示一些图像:

 <Image Source="{Binding Path=TemplateImagePath, Mode=TwoWay}"  Grid.Row="3" Grid.Column="2"  Width="400" Height="200"/>

并通过浏览某个目录在构造函数后面的代码中设置它的绑定属性,下面是代码:

DirectoryInfo Dir = new DirectoryInfo(@"D:/Template");
            if (Dir.Exists)
            {
                if (Dir.GetFiles().Count() > 0)
                {
                    foreach (FileInfo item in Dir.GetFiles())
                    {
                        TemplateImagePath = item.FullName;
                    }
                }
            }

但是如果用户上传了其他图片,那么我需要删除这个旧图片,我正在按照以下方式进行操作,并将图片绑定设置为 null:

DirectoryInfo Dir = new DirectoryInfo(@"D:/Template");
                if (Dir.Exists)
                {
                    if (Dir.GetFiles().Count() > 0)
                    {
                        foreach (FileInfo item in Dir.GetFiles())
                        {
                            TemplateImagePath= null;
                            File.Delete(item.FullName);
                        }
                    }
                }

但我收到异常,无法删除其他进程使用的文件。 如何删除?

【问题讨论】:

  • 您是否尝试过不使用双向绑定?另一个可行的解决方案是不直接设置路径,而是从路径创建 BitmapImage 并绑定到该位图图像。
  • 怎么做。我是 WPF 的新手。任何代码示例
  • 抱歉,没时间,请使用谷歌。

标签: wpf c#-4.0 file-io ioexception


【解决方案1】:

为了能够在 ImageControl 中显示图像时将其删除,您必须创建一个新的 BitmapImageBitmapFrame 对象,该对象设置了 BitmapCacheOption.OnLoad。然后会立即从文件中加载位图,之后文件不会被锁定。

将您的属性从 string TemplateImagePath 更改为 ImageSource TemplateImage 并像这样绑定:

<Image Source="{Binding TemplateImage}"/>

像这样设置TemplateImage属性:

BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(item.FullName);
image.EndInit();
TemplateImage = image;

或者这个:

TemplateImage = BitmapFrame.Create(
    new Uri(item.FullName),
    BitmapCreateOptions.None,
    BitmapCacheOption.OnLoad);

如果您想继续绑定到您的 TemplateImagePath 属性,您可以改用 binding converter 将字符串转换为 ImageSource,如上所示。

【讨论】:

  • 我还需要添加 'System.GC.Collect(); System.GC.WaitForPendingFinalizers();'在删除该行之前的文件之前: File.Delete(item.FullName)
  • 在这上面花了很多时间,但添加了 'GC.Collect();'和'GC.WaitForPendingFinalizers();'在删除之前解决了我的问题。谢谢@SST
  • @Jon 你可能还想看看这个:stackoverflow.com/q/13262548/1136211。虽然触发 GC 可能会起作用,但“正确”(即记录在案的)解决方案是设置 StreamSource 而不是 UriSource 属性。
  • @Clemens 谢谢,我去看看
  • 你是如何处理视频的?
【解决方案2】:

根据 Clemens 的建议,这是具有良好代码重用性的绑定转换器:

namespace Controls
{
    [ValueConversion(typeof(String), typeof(ImageSource))]
    public class StringToImageSourceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is string valueString))
            {
                return null;
            }
            try
            {
                ImageSource image = BitmapFrame.Create(new Uri(valueString), BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.OnLoad);
                return image;
            }
            catch { return null; }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

还有一个用于绑定的字符串,例如

public string MyImageString { get; set; } = @"C:\test.jpg"

在 UI 中使用了转换器,在我的例子中来自名为“Controls”的库

<Window x:Class="MainFrame"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:Controls;assembly=Controls">
    <Window.Resources>
        <controls:StringToImageSourceConverter x:Key="StringToImageSourceConverter" />
    </Window.Resources>
    <Grid>
        <Image Source="{Binding MyImageString, Converter={StaticResource StringToImageSourceConverter}}" />
    </Grid>
</Window>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 2012-01-29
    相关资源
    最近更新 更多