【发布时间】:2012-02-11 08:36:13
【问题描述】:
我们有一个具有以下架构的客户端应用程序:一个管理器进程管理几个工作进程(读取器和写入器)并定期查询服务器以获取版本更新。如果版本更新可用,则管理器将其下载到客户端计算机,关闭工作线程,启动更新程序进程以处理更新并退出。更新程序在启动时接收管理器 PID 和更新文件位置;然后等待 manager 退出,备份 manager 和 workers 的所有文件,重新创建他们的目录并将新版本文件传播到新目录。
当按照描述执行此过程时,第一次调用 Directory.Move(string, string)(用于备份管理器目录)会引发 IOException。奇怪的是,如果我让管理器在不启动更新程序的情况下关闭,然后自己启动更新程序可执行文件,则不会抛出异常。
用于管理工作线程的管理器代码:
public void Run()
{
_config = GetConfiguration();
Process reader, writer;
//Start reader and writer with appropriate arguments
//Keep reader and writer alive
reader.Kill();
writer.Kill();
reader.WaitForExit();
writer.WaitForExit();
reader.Dispose();
writer.Dispose();
}
查询数据库的管理器代码:
EndpointAddress endpoint;
BasicHttpBinding httpBinding = new BasicHttpBinding();
httpBinding.MaxReceivedMessageSize = 2000000000;
ChannelFactory<IService> chanFactory = new ChannelFactory<IService>(httpBinding);
IService service;
try
{
endpoint = new EndpointAddress(ConfigurationManager.AppSettings["Service URL"]);
service = chanFactory.CreateChannel(endpoint);
UpdateInstructions instructions = service.GetUpdateInstructions(_config.SiteID, Assembly.GetExecutingAssembly().GetName().Version.ToString(), _config.Version);
HandleUpdateInstructions(instructions); //Downloads files and starts the updater process
}
catch (Exception ex)
{
//Report exception
}
finally
{
if (chanFactory.State != CommunicationState.Faulted)
chanFactory.Close();
}
用于启动更新进程的管理器代码:
private void StartUpdater(string updateFilePath, string configFilePath)
{
ProcessStartInfo updaterStartInfo = new ProcessStartInfo(_config.UpdaterExePath, string.Format("{0} \"{1}\" \"{2}\"", Process.GetCurrentProcess().Id, updateFilePath, configFilePath));
Process updater = Process.Start(updaterStartInfo);
updater.Dispose();
}
等待管理器关闭的更新代码:
bool isManagerUp = true;
while (isManagerUp)
{
try
{
Process managerProcess = Process.GetProcessById(bDoxForceManagerPID);
managerProcess.WaitForExit();
managerProcess.Dispose();
isManagerUp = false;
}
catch
{
isManagerUp = false;
}
}
更新模块的更新代码:
//updateDirectory is the directory of the new files to be inserted, moduleDirectory is the working directory of the module that will be updated, in this case the manager
private void UpdateModule(DirectoryInfo updateDirectory, DirectoryInfo moduleDirectory)
{
string backupDirectory = MakeBackupDirectoryFullPath(moduleDirectory.Parent.FullName);
Directory.Move(moduleDirectory.FullName, backupDirectory); // IOException as described above.
Directory.CreateDirectory(moduleDirectory.FullName);
foreach (FileInfo updateFile in updateDirectory.EnumerateFiles())
{
string newFilePath = moduleDirectory.FullName + "\\" + updateFile.Name;
File.Copy(updateFile.FullName, newFilePath);
}
Directory.Delete(updateDirectory.FullName, true);
}
【问题讨论】:
-
请显示 MakeBackupDirectoryFullPath 方法代码
-
@MrMush:吞下带有空
catch块的异常会使调试变得更加困难。例如,在您的 Updater 代码中,isManagerUp变量是完全多余的,因为无论发生什么都将其设置为 false。 -
1 - 您何时调用 StartUpdater ?在while循环之后?无论如何,请相信消息:您的目录仍然有锁定访问权限。这意味着您之前的进程肯定仍在使用管理器目录。我的猜测是,当您调用 StartUpdater 时 managerProcess 尚未完成,或者该目录仍在以某种方式被另一个进程使用。您应该使用锁仔细调试。
-
2 - 截至您提到的使用工作线程的另一个进程仍在以某种方式使用该目录,我敢打赌,当您已经启动更新程序时,它们还没有完成。一个简单的检查是在调用更新程序之前放置一个 Thread.Sleep(10000),它可能会起作用
-
@Groo:这只是我的代码的简化版本,虽然它很长,但我不想用不必要的代码让你厌烦。
标签: c# .net wcf process ioexception