C# 无法删除之前在 Window 中打开的 pdf
C# Unable to delete a pdf that was previously open in a Window
我有一个在 window 中打开的 PDF 文件。 window 已关闭,然后我尝试删除该文件并收到正在使用的错误。由于打开它的 window 已关闭,因此不应再锁定它。任何建议将不胜感激。
我有一个本地变量 _window
private Window _window;
我有以下代码可以在 window
中打开 PDF
_window = new Window
{
Title = "PDF Viewer",
Content = new WebBrowserView(),
DataContext = new WebBrowserViewModel
{
Uri = _pdfPathFull
},
IsEnabled = false
};
_window.Show();
window关闭如下
private void ClosePDF()
{
if (_window != null)
{
window.DataContext = new WebBrowserViewModel
{
Uri = "about:blank"
};
_window.Close();
_window = null;
}
}
我有以下代码试图删除在 window 中打开的文件,它总是失败并显示错误 "The process cannot access the file \ServerName\FileName.pdf because it is being used by another process."
ClosePDF();
bool fileDeleted = false;
int tryCount = 0;
FileInfo targetFile = new FileInfo(_pdfPathFull);
while (!fileDeleted && tryCount <= 50)
{
System.Threading.Thread.Sleep(500);
try
{
targetFile.Delete();
fileDeleted = true;
}
catch(Exception ex)
{
if (tryCount == 50)
throw (ex);
}
tryCount++;
}
这是 WebBrowserViewModel 的定义。这是所有遗留代码,我只是被要求添加删除功能。
public class WebBrowserViewModel : AppViewModel
{
private string _uri = string.Empty;
public WebBrowserViewModel()
{
}
public string Uri
{
get { return _uri; }
set { Set("Uri", ref _uri, value); }
}
}
我认为问题出在这里:
这样做:
DataContext = new WebBrowserViewModel
{
Uri = _pdfPathFull
},
在内存中创建一个对象,即使在 DataContext 设置为 "about:blank"
时,该对象也会继续保存 pdf 引用
我建议取一个参考变量并改用它。确保在 Window 关闭后取消引用它。确保 Window 对象也从调用函数中清除。
这就是我更新代码的方式:
添加一个新的私有变量:
private Window _window;
private FrameworkElement _fwElement;
下一组更改:
_fwElement = new FrameworkElement();
_fwElement.DataContext = new WebBrowserViewModel { Uri = _pdfPathFull };
_window = new Window
{
Title = "PDF Viewer",
Content = new WebBrowserView(),
DataContext = _fwElement.DataContext,
IsEnabled = false
};
_window.Show();
现在当我们关闭 Window:
private void ClosePDF()
{
if (_window != null)
{
if(_fwElement != null)
{
_fwElement.DataContext = null;
}
window.DataContext = new WebBrowserViewModel
{
Uri = "about:blank"
};
_fwElement = null;
_window.Close();
_window = null;
GC.Collect();
}
}
你有什么问题?
如果您想知道哪个进程正在锁定您的文件,一个简单的方法是 运行 openfiles /query /fo table
,然后解析输出。有关如何获取输出的信息,请参阅 ProcessStartInfo.RedirectStandardOutput。如果是本地进程,则需要设置一次,openfiles /local on
并重新启动。
顺便说一句,由于网络延迟,它可以锁定在插座的两端,甚至可以锁定在您的 PC 和 \ServerName
之间。
对临时文件使用网络共享很少是个好主意。请改用本地目录。如果由于法律或其他要求而不能,请使用 RAM 而不是磁盘,例如为嵌入式浏览器实施自定义 URI 方案,并以自定义方案 URL.
提供 pdf
更简单但不太可靠的解决方法是在延迟一段时间后重试删除该文件。我会使用 100-500 毫秒的延迟并重试 5-10 秒。
我在 WinForms 中遇到了这个问题,我发现解决这个问题的唯一可靠方法是制作 PDF 的临时副本并显示副本,这样原件就不会被锁定。
据我所知,没有直接的方法可以指示网络浏览器关闭文件。
当然,您仍然需要删除临时副本,但您可以在您的应用下次启动时删除,或者继续重试计时器等。
将 DataContext 分配给其他东西只会孤立旧的,当程序绕过它时将其丢弃,而您的删除循环中的任何内容都不会这样做。
您这里有一个非托管资源,编译器不会为您清理。您必须明确地处理有问题的对象,并希望下面的代码编写得足够好。我从来没有用 PDF 文件尝试过这个,在我对 XPS 文件的有限尝试中,我最终得到了 SSS 的解决方案(临时副本可以是 identified/killed,下次程序是 运行。)
我有一个在 window 中打开的 PDF 文件。 window 已关闭,然后我尝试删除该文件并收到正在使用的错误。由于打开它的 window 已关闭,因此不应再锁定它。任何建议将不胜感激。
我有一个本地变量 _window
private Window _window;
我有以下代码可以在 window
中打开 PDF_window = new Window
{
Title = "PDF Viewer",
Content = new WebBrowserView(),
DataContext = new WebBrowserViewModel
{
Uri = _pdfPathFull
},
IsEnabled = false
};
_window.Show();
window关闭如下
private void ClosePDF()
{
if (_window != null)
{
window.DataContext = new WebBrowserViewModel
{
Uri = "about:blank"
};
_window.Close();
_window = null;
}
}
我有以下代码试图删除在 window 中打开的文件,它总是失败并显示错误 "The process cannot access the file \ServerName\FileName.pdf because it is being used by another process."
ClosePDF();
bool fileDeleted = false;
int tryCount = 0;
FileInfo targetFile = new FileInfo(_pdfPathFull);
while (!fileDeleted && tryCount <= 50)
{
System.Threading.Thread.Sleep(500);
try
{
targetFile.Delete();
fileDeleted = true;
}
catch(Exception ex)
{
if (tryCount == 50)
throw (ex);
}
tryCount++;
}
这是 WebBrowserViewModel 的定义。这是所有遗留代码,我只是被要求添加删除功能。
public class WebBrowserViewModel : AppViewModel
{
private string _uri = string.Empty;
public WebBrowserViewModel()
{
}
public string Uri
{
get { return _uri; }
set { Set("Uri", ref _uri, value); }
}
}
我认为问题出在这里:
这样做:
DataContext = new WebBrowserViewModel
{
Uri = _pdfPathFull
},
在内存中创建一个对象,即使在 DataContext 设置为 "about:blank"
时,该对象也会继续保存 pdf 引用我建议取一个参考变量并改用它。确保在 Window 关闭后取消引用它。确保 Window 对象也从调用函数中清除。
这就是我更新代码的方式:
添加一个新的私有变量:
private Window _window;
private FrameworkElement _fwElement;
下一组更改:
_fwElement = new FrameworkElement();
_fwElement.DataContext = new WebBrowserViewModel { Uri = _pdfPathFull };
_window = new Window
{
Title = "PDF Viewer",
Content = new WebBrowserView(),
DataContext = _fwElement.DataContext,
IsEnabled = false
};
_window.Show();
现在当我们关闭 Window:
private void ClosePDF()
{
if (_window != null)
{
if(_fwElement != null)
{
_fwElement.DataContext = null;
}
window.DataContext = new WebBrowserViewModel
{
Uri = "about:blank"
};
_fwElement = null;
_window.Close();
_window = null;
GC.Collect();
}
}
你有什么问题?
如果您想知道哪个进程正在锁定您的文件,一个简单的方法是 运行 openfiles /query /fo table
,然后解析输出。有关如何获取输出的信息,请参阅 ProcessStartInfo.RedirectStandardOutput。如果是本地进程,则需要设置一次,openfiles /local on
并重新启动。
顺便说一句,由于网络延迟,它可以锁定在插座的两端,甚至可以锁定在您的 PC 和 \ServerName
之间。
对临时文件使用网络共享很少是个好主意。请改用本地目录。如果由于法律或其他要求而不能,请使用 RAM 而不是磁盘,例如为嵌入式浏览器实施自定义 URI 方案,并以自定义方案 URL.
提供 pdf更简单但不太可靠的解决方法是在延迟一段时间后重试删除该文件。我会使用 100-500 毫秒的延迟并重试 5-10 秒。
我在 WinForms 中遇到了这个问题,我发现解决这个问题的唯一可靠方法是制作 PDF 的临时副本并显示副本,这样原件就不会被锁定。
据我所知,没有直接的方法可以指示网络浏览器关闭文件。
当然,您仍然需要删除临时副本,但您可以在您的应用下次启动时删除,或者继续重试计时器等。
将 DataContext 分配给其他东西只会孤立旧的,当程序绕过它时将其丢弃,而您的删除循环中的任何内容都不会这样做。
您这里有一个非托管资源,编译器不会为您清理。您必须明确地处理有问题的对象,并希望下面的代码编写得足够好。我从来没有用 PDF 文件尝试过这个,在我对 XPS 文件的有限尝试中,我最终得到了 SSS 的解决方案(临时副本可以是 identified/killed,下次程序是 运行。)