我正在尝试使用here概述的方法构建单个实例应用程序.
我尝试使用该解决方案的原因是我需要将第二次尝试启动应用程序的命令行传递给第一个实例,这似乎是实现这一目标的最简单方法.
我需要支持的OS风格:
> Windows XP SP3
> Windows 7 32位
> Windows 7 64位
我已经在所有三个操作系统版本上工作,但是,我有一台机器与Windows 7 32Bit,其中崩溃与CantStartSingleInstanceException.
这是代码:
SingleInstanceController.cs:
using System;
using Microsoft.VisualBasic.ApplicationServices;
namespace SingleInstanceTest
{
public class SingleInstanceController : WindowsFormsApplicationBase
{
public SingleInstanceController()
{
IsSingleInstance = true;
}
protected override void OnCreateMainForm()
{
base.OnCreateMainForm();
Form1 f = new Form1();
MainForm = f;
// process first command line
f.SetCommandLine(Environment.GetCommandLineArgs());
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
base.OnStartupNextInstance(eventArgs);
Form1 f = MainForm as Form1;
// process subsequent command lines
f.SetCommandLine(eventArgs.CommandLine);
}
}
}
Program.cs中:
using System;
using System.Windows.Forms;
namespace SingleInstanceTest
{
static class Program
{
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SingleInstanceController si = new SingleInstanceController();
// This triggers the crash on one machine when starting the
// app for the second time
si.Run(Environment.GetCommandLineArgs());
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
// this is triggered with CantStartSingleInstanceException
MessageBox.Show(e.ToString(),"ThreadException");
MessageBox.Show(e.Exception.ToString(), "ThreadException");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(e.ToString(), "UnhandledException");
MessageBox.Show(e.ExceptionObject.ToString(), "UnhandledException");
}
}
}
出于测试目的,表单只是一个包含显示命令行参数的列表框的普通表单.
任何想法为什么这不适用于那台机器?我已经花了两天时间摆弄这个并且无法弄明白……
解决方法:
我遇到了同样的问题,但我不认为它与Windows 7或32位有关.事实证明,这是一个性能问题.不幸的是,我找不到WindowsFormsApplicationBase的源代码
但它使用网络与主应用程序通信,因此可能涉及超时.当主应用程序不得不做很多网络I / O时,它尤其糟糕.当主应用程序没有快速响应Run to Run的调用时,抛出此异常.
我通过微调进程,任务和线程来解决它,所以首先回答了调用.
通过使用互斥和适当的IPC摆脱WindowsFormsApplicationBase,我实际上不仅可以选择超时,还可以捕获任何异常!实际上,对于某些类型的IPC,甚至不需要互斥锁.
有关该主题的更多信息,请参阅此精美文章:
https://www.codeproject.com/Articles/1089841/SingleInstance-NET
我选择的两个最脏的解决方法:
>捕获异常并在几毫秒后再次尝试.
>经过一些测试,在基础应用程序中生成一个低优先级的新线程似乎是一个好主意(至少在我的场景中).
public void SetCommandLineInThread(string[] args) {
new Thread(() => {
SetCommandLine(args);
}) { IsBackground = true, Priority = ThreadPriority.Lowest }.Start();
}
请注意,我尽快复制命令行args.
var args = e.CommandLine.ToArray();