2012-03-16 61 views
4

我在嘗試使用概述here的方法構建單個實例應用程序。嘗試啓動第二個實例時發生CantStartSingleInstanceException

我試着用這個解決方案的原因是,我需要從第二次嘗試傳遞命令行來啓動應用程序到第一個實例,這似乎是最簡單的方法來完成。

OS口味我需要支持:

  • 的Windows XP SP3
  • 的Windows 7 32位
  • Windows 7的64位

我得到它的工作在所有三個OS版本,但是,我有一臺機器與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"); 
    } 
    } 
} 

出於測試目的,形式爲含有一個顯示列表框只是一個普通的形式命令行參數。

任何想法,爲什麼這不適用於一臺機器?我已經擺弄這兩天了,不知道它...

回答

2

我遇到了同樣的問題,但我不認爲它與Windows 7或32位有關。結果發現,這是一個性能問題。不幸的是,我找不到WindowsFormsApplicationBase 的源代碼,但它使用網絡與主應用程序進行通信,因此可能會涉及超時。當主應用程序無論如何需要執行大量的網絡I/O時,情況尤其糟糕。當主應用程序未響應足夠快的調用時,將拋出此異常。

我解決了它通過微調進程,任務ans線程,所以呼叫得到回答第一。

並通過使用互斥鎖和適當的IPC來擺脫WindowsFormsApplicationBase,其中我實際上不僅可以選擇超時,還可以捕獲任何異常!實際上,對某些IPC來說,甚至不需要互斥體。

看到這個美好的文章以獲得更多關於該主題: https://www.codeproject.com/Articles/1089841/SingleInstance-NET

兩個dirtymost解決方法我選擇:

  1. 捕捉異常,並稍後再嘗試幾毫秒。
  2. 經過一些測試後,在基本應用程序中產生一個低優先級的新線程似乎是一個好主意(至少在我的場景中)。

    public void SetCommandLineInThread(string[] args) { 
        new Thread(() => { 
         SetCommandLine(args); 
        }) { IsBackground = true, Priority = ThreadPriority.Lowest }.Start(); 
    } 
    

注意,我做的命令行的副本儘快ARG遊戲成爲可能。

var args = e.CommandLine.ToArray(); 
相關問題