【发布时间】:2012-09-14 15:08:56
【问题描述】:
好的,到此为止。我在许多其他网站中搜索了这个网站,似乎没有人可以给我一个直接的答案,所以我将尝试直接询问。在这个问题上呆了大约 3 天,我不能再浪费时间了。
目标:我正在构建的应用程序是在 WPF 中,将用作我的设计团队和我将很快开展的项目的错误跟踪器。由于我们将使用 C++ 构建游戏,因此发生的大多数错误都将具有视觉元素,因此我包含了在用户将错误添加到列表时提供相关错误图像的功能。然后我拍摄该图像并将其保存到本地目录(用于测试)。现在,Error 对象中的图像路径指向了通向本地目录的路径。此功能已经过测试并且工作正常。当我想从列表中删除一个错误时,我的问题就出现了。我收到了那个非常臭名昭著的“IO Exception”,说我要删除的图像正在被另一个进程使用。
到目前为止: 起初我尝试了非常优雅的解决方案,但与所有事情一样,你只是想看看你是否可以让事情完全发挥作用。所以我现在使用的大部分代码都是实验性的和激进的。因此,请在查看时注意所使用的代码是出于绝望,因此可能已经尝试过任何“简单”的解决方案(我确实对此进行了很多研究,因为我讨厌这样做)。我能想到的事情是荒谬的处置和强制垃圾收集被调用,所以请不要评论这种做法的负面性质,我很清楚:)。
守则
保存图片到本地目录
public void OnBrowseClick()
{
Microsoft.Win32.OpenFileDialog openBox = new Microsoft.Win32.OpenFileDialog();
// Show dialog box to user and grab output
Nullable<bool> result = openBox.ShowDialog();
if (result == true)
{
// Create temp variable to hold local path string
string localPath = Directory.GetCurrentDirectory();
// Grab the extension of the specified file path
string extension = openBox.FileName.Substring(openBox.FileName.LastIndexOf("\\"));
// Add extension to local path
localPath += extension;
// Create local copy of image at given file path (being ridiculous at this point)
using (Stream stream = new FileStream(openBox.FileName, FileMode.Open, FileAccess.ReadWrite))
{
using (Bitmap bmp = LoadImage(stream))
{
using (Bitmap temp = (Bitmap)bmp.Clone())
{
temp.Save(localPath);
temp.Dispose();
}
bmp.Dispose();
}
stream.Dispose();
}
// Set the URL in the image text box (UI stuff)
LocalError.ImagePath = localPath;
}
}
下面是上面函数中用到的LoadImage函数
private Bitmap LoadImage(Stream stream)
{
Bitmap retval = null;
using (Bitmap bitmap = new Bitmap(stream))
{
retval = new Bitmap(bitmap.Width, bitmap.Height, bitmap.PixelFormat);
using (Graphics gdi = Graphics.FromImage(retval))
{
gdi.DrawImageUnscaled(bitmap, 0, 0);
gdi.Flush();
gdi.Dispose();
bitmap.Dispose();
}
}
// Garbage collection here to be safe
GC.WaitForPendingFinalizers();
GC.Collect();
return retval;
}
最后我们来到我尝试删除图像的地方
public void OnDeleteClick()
{
// Ask user to make sure they want to delete selected item(s)
MessageBoxResult result = MessageBox.Show("Are you sure you want to delete selected item(s) from the list?",
"Delete", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
for( int i = 0; i < Parent.ErrorListControl.ErrorDataGrid.SelectedItems.Count; ++i)
{
// Get path to image
string path = (Parent.ErrorListControl.ErrorDataGrid.SelectedItems[i] as Error).ImagePath;
// Even tried calling garbage collection here!!!!!
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
File.Delete(path);
// Remove the error from the error list
Parent.ErrorListVM.ErrorList.Remove((Error)Parent.ErrorListControl.ErrorDataGrid.SelectedItems[i]);
// Decrement counter because we altered the list while in a loop
i--;
}
}
}
注意事项:如果有人希望我进一步解释任何事情,或者如果您需要知道我遗漏的内容,请询问我会尽快回复您!在这一点上,任何建议都是有帮助的,我绝对不知道我做错了什么。我通常只在 C++ 环境中编程,所以我倾向于管理我自己的内存,这整个“垃圾收集”的事情真的给我们的项目带来了麻烦! (题外话:我不知道为什么我没有得到任何颜色突出显示,所以我向任何花时间阅读本文的人道歉)。
【问题讨论】:
-
能否说明原图的出处?是您的应用程序创建它,还是用户通过单击“浏览”按钮提供他们选择的任何图像? Delete函数,是不是应该删除用户使用OpenFileDialog指向的原始图像?
-
您好,感谢您抽出宝贵时间帮助我。
-
对不起,按回车键 原始图像是由用户通过浏览按钮选择的。我所做的只是将其加载并存储在其他地方(本地文件夹,bin -> 调试) 目的是删除图像的本地副本,而不是原始图像。这只会删除保存到我项目中“Bin->Debug”文件夹中的图像(仅使用此目录进行测试)。
-
难道不能只使用 File.Copy 将文件复制到本地存储吗?
-
可能还值得一提的是,我正在使用 MVVM 设计模式——有点失落。