0

当我调用 Application.Restart() 方法时,会出现检测应用程序当前是否正在运行的错误。有没有办法解决?

    static void Main(string[] args)
    {
        string proc = Process.GetCurrentProcess().ProcessName;
        Process[] processes = Process.GetProcessesByName(proc);
        if (processes.Length > 1)
        {
            MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
4

5 回答 5

3

使用互斥锁。例如:关闭时最小化到系统托盘的单实例应用程序。这个例子比你可能需要的更复杂,但使用 Mutex 的基本单实例概念效果很好。

于 2009-10-30T03:23:30.187 回答
1

最有效的方法是继承VB.Net的WindowsFormsApplicationBase类,也可以在C#中使用,并将IsSingleInstance属性设置为true. 这使用互斥体,如果重命名 EXE 文件,它将继续工作。

于 2009-10-30T03:23:56.793 回答
1

我遇到了类似的问题,但我的问题与无法管理的内存泄漏有关,我在必须 24/7 运行的应用程序上找不到该问题。我与客户同意,如果内存消耗超过定义值,则重新启动应用程序的安全时间是凌晨 03:00。

我试过Application.Restart了,但由于它似乎使用了一些在新实例已经运行时启动新实例的机制,所以我选择了另一种方案。我使用了文件系统处理持续存在直到创建它们的进程死亡的技巧。所以,从应用程序,我把文件放到磁盘上,但没有Dispose()处理。我也使用该文件来发送“我自己”的可执行文件和起始目录(以增加灵活性)。

代码:

_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
    FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
    WorkingDirectory = Application.StartupPath,
    Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();

Close()最后将启动应用程序关闭,并且我在StreamWriter这里使用的文件句柄将保持打开状态,直到进程真正终止。然后...

Restarter.exe 开始行动。它尝试以独占模式读取文件,防止它获得访问权限,直到主应用程序没有死,然后启动主应用程序,删除文件并存在。我想它不能更简单:

static void Main(string[] args)
{
    string filename = args[0];
    DateTime start = DateTime.Now;
    bool done = false;
    while ((DateTime.Now - start).TotalSeconds < 30 && !done)
    {
        try
        {
            StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
            string[] runData = new string[2];
            runData[0] = sr.ReadLine();
            runData[1] = sr.ReadLine();
            Thread.Sleep(1000);
            Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
            sr.Dispose();
            File.Delete(filename);
            done = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Thread.Sleep(1000);
    }
}
于 2011-04-09T09:14:54.630 回答
0

最简单的方法是在退出之前添加延迟。

换句话说,

string proc = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcessesByName(proc).Length > 1) {
    Thread.Sleep(500);      //500 milliseconds; you might need to wait longer
    if (Process.GetProcessesByName(proc).Length > 1) {
        MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
}    //no else
于 2009-10-30T03:19:11.123 回答
0

尝试将您的重新启动代码作为侦听器方法连接到Application.ApplicationExit事件。然后您将调用 Application.Exit 以使代码间接运行。

编辑:添加代码示例:

例如,当用户单击重启按钮或应用决定重启时,调用此 RestartMeSmartly() 方法。您不必担心欺骗 - 它会起作用。

void RestartMeSmartly() {
    Application.ApplicationExit += BeforeExiting;
    Application.Exit();
}

void BeforeExiting(object sender, EventArgs args) {
    Application.Restart();
}
于 2009-10-30T03:22:27.240 回答