重启当前进程 C#

7

我有一个应用程序,其中包含一些安装程序,我想重新加载与该应用程序相关的所有内容,因此我想重启进程。我搜索并看到了Application.Restart()及其缺点,想知道完成我所需的最佳方法 - 关闭进程并重新启动它,或者是否有更好的方法来重新初始化所有对象。


3
您能详细说明一下Restart()的缺点吗?它会关闭应用程序并在原始上下文中重新启动,这似乎是您想要的。 - Frédéric Hamidi
3个回答

5
我会启动一个新的实例,然后退出当前实例:
private void Restart()
{
    Process.Start(Application.ExecutablePath);

    //some time to start the new instance.
    Thread.Sleep(2000);

    Environment.Exit(-1);//Force termination of the current process.
}

private static void Main()
{
    //wait because we maybe here becuase of the system is restarted so give it some time to clear the old instance first
    Thread.Sleep(5000);

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(...
}

编辑:然而,您还应该考虑添加某种互斥锁以允许一次只运行一个应用程序,例如:

private const string OneInstanceMutexName = @"Global\MyUniqueName";

private static void Main()
{
    Thread.Sleep(5000);
    bool firstInstance = false;
    using (System.Threading.Mutex _oneInstanceMutex = new System.Threading.Mutex(true, OneInstanceMutexName, out firstInstance))
    {
        if (firstInstance)
        {
            //....
        }
     }
}

1
不要使用Thread.Sleep,相反你应该在Main函数中杀死所有运行着与自己相同可执行文件的进程(除了你自己的进程)。 - sternr
@sternr:我在代码中添加了“mutex”,这样同一时间只允许运行一个实例。 - Jalal Said
1
你确定System.Threading.Mutex在进程之间是共享的吗? - sternr
当然我确定,命名为MutexSemaphores的对象可以在进程之间共享。请注意,我的命名互斥锁在名称前面使用Global\,因此即使在会话中它也可以工作。 - Jalal Said
2
如果您的第一个应用程序在内存中停留时间稍长(由于任何原因),直到第二个实例唤醒,两者都将退出。但是使用Thread.Sleep解决竞争条件并不是一种解决方案。每次启动应用程序时挂起5秒钟的应用程序会让我感到烦恼。而且,“Global\”前缀只有在服务器运行终端服务时才会有所区别。 - vgru
显示剩余3条评论

0
在我的WPF应用程序中(通过互斥锁实现单个实例),我使用Process.Start和ProcessStartInfo,向其发送定时的cmd命令以重新启动应用程序:
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C ping 127.0.0.1 -n 2 && \"" + Application.GetCurrentProcess()+ "\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
ShellView.Close();

该命令被发送到操作系统,ping 命令会暂停脚本 2-3 秒钟,在此期间应用程序已经从 ShellView.Close() 中退出,然后 ping 命令之后的下一个命令会再次启动它。

注意:\" 在路径周围添加引号,以防其包含空格,否则 cmd 将无法处理。 (我的代码参考 这个答案


使用ping命令来延迟某些操作?我可能会选择Thread.sleep。最小惊奇原则等等。如果您的进程占用了需要在新实例接管之前释放的资源,则传递一个参数,指示新实例在尝试声明这些资源之前暂停几秒钟。 - LOAS
我曾经使用ping命令在命令行上延迟事情,但后来我发现了'timeout'。 - Daniel Mošmondor

-1

我认为启动一个新进程并关闭现有的进程是最好的方法。这样,您就可以在启动和关闭进程之间为现有进程设置一些应用程序状态。

这个线程讨论了为什么Application.Restart()在某些情况下可能无法正常工作。

System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
// Set any state that is required to close your current process.
Application.Current.Shutdown();

或者

System.Diagnostics.Process.Start(Application.ExecutablePath);
// Set any state that is required to close your current process.
Application.Exit();

如果您关闭当前进程,系统将无法访问Process.Start,您应该先启动新实例,然后再关闭当前实例。 - Jalal Said
下投票的原因是因为他想重新启动当前进程,而你的答案并没有解决这个问题。 - Oskar Kjellin
1
正如@jalal所说。你首先要结束进程,然后再启动新的进程。自杀会导致你无法启动新的进程。被终止的进程不能启动新的进程。 - Oskar Kjellin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接