我有一个承载winform
服务的WCF
应用程序。
此应用程序支持多个客户端,每个客户端向我的应用程序发送string
代表文件名。我的应用程序开始处理并完成工作。
在流程结束后(每个流程在有限时间内打开),我的流程会引发退出事件。
创建将文件复制到新位置的过程的文件,然后删除旧文件。此时,大多数情况都会失败,因为我的文件仍在使用中。所以我想知道如何处理这个问题。
这就是我打开我的过程的方式:
ProcessStartInfo tsharkStartInfo = new ProcessStartInfo();
Process pros = new Process();
tsharkStartInfo.FileName = processToInvoke;
tsharkStartInfo.RedirectStandardOutput = true;
tsharkStartInfo.RedirectStandardError = true;
tsharkStartInfo.RedirectStandardInput = true;
tsharkStartInfo.UseShellExecute = false;
tsharkStartInfo.CreateNoWindow = true;
tsharkStartInfo.Arguments = args;
pros.StartInfo = tsharkStartInfo;
pros.ErrorDataReceived += pros_ErrorDataReceived;
pros.OutputDataReceived += pros_OutputDataReceived;
pros.EnableRaisingEvents = true;
pros.Start();
pros.BeginOutputReadLine();
pros.BeginErrorReadLine();
pros.EnableRaisingEvents = true;
pros.Exited += (object sender, EventArgs e) =>
{
if (ProcessExitedEvent != null)
ProcessExitedEvent(pros.Id); // Raised this event when my process exit
};
private void processExitEvent()
{
// copy the file to new location
// delete the old file
}
我应该这样做:
ManualResetEvent mre = new ManualResetEvent(false);
private void processExitEvent()
{
// copy the file to new location
mre.WaitOne(2000); // wait 2 seconds to ensure my file not longer in use
// delete the old file
}
所以我的问题是,这个解决方案是否只会阻止当前线程或所有客户端线程?
答案 0 :(得分:0)
它只会阻止当前线程。如果它会阻塞所有线程,就没有线程能够调用mre.Set()
!
如果你想要的只是等待(mre.Set()
没有在任何地方调用过),你可以改用Thread.Sleep(2000);
。
答案 1 :(得分:0)
我觉得你的方法存在一些问题......
首先,听起来你在游泳条件下游泳......添加sleep(2000)
可能会解决这个问题......但不是每次都有。这绝对是错误的做法。您希望确保在继续操作之前绝对关闭该文件。这意味着,文件应该在event
被提升之前关闭。
其次,听起来你正试图对一个尚未关闭的文件做一些事情......
在C#中始终避免这种情况的一个可靠方法是使用using
块。
所以我要说你有这样的事情:
using (FileStream fs = File.OpenRead(x))
{
// Copy the file...
// End of scope - This will close the file.
}
// Raise exit event.
使用using
语句的好处是,您确切知道,一旦退出此块,文件就会被关闭。
最终......你只是想避免依赖sleep(2000)
甚至WaitOne(2000)
之类的东西。这些可能会产生不可预测的结果。