2012-08-08 78 views
0

协作者使用处理连接到Sparkfun RFID阅读器构建了一个原型,我认为使用USB上的串行连接。我们已经将原型部署到了许多审判者的家中,而我愚蠢地忽略的一个常见使用场景是用户切换。因此,我正在编写一个包装器,确保只有一个原型应用程序实例在机器上的所有用户上运行。使用EventWaitHandle确保跨多个用户的单个实例

我正在测试我的第一个刺这个简单的控制台应用程序。下面的代码:

static void Main(string[] args) 
    { 
     // http://stackoverflow.com/a/2590446/575530 
     var users = new SecurityIdentifier(WellKnownSidType.WorldSid, null); 
     var rule = new EventWaitHandleAccessRule(users, EventWaitHandleRights.FullControl, AccessControlType.Allow); 
     var security = new EventWaitHandleSecurity(); 
     security.AddAccessRule(rule); 
     bool createdStartup; 
     using (var whStartup = new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppStartupEvent", out createdStartup, security)) 
     { 
      bool createdShutdown; 
      using (var whShutdown = new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppShutdownEvent", out createdShutdown, security)) 
      { 
       Console.WriteLine("Let other instances shutdown"); 
       whStartup.Set(); 
       Console.WriteLine("If other instances exist wait for them to shutdown"); 
       if (!createdShutdown) 
       { 
        whShutdown.WaitOne(); 
       } 
       whShutdown.Reset(); 
       Console.WriteLine("Start tray app"); 
       var tokenProc = Process.Start(@"C:\Temp\FAMILY3_WIN\TokensApp.exe"); 
       Console.WriteLine(tokenProc.ProcessName); 
       Console.WriteLine("Wait to see if another instance to tries to start"); 
       whStartup.Reset(); 
       whStartup.WaitOne(); 
       Console.WriteLine("Shutdown if another instance starts"); 
       //if (tokenProc != null) tokenProc.Kill(); 
       foreach (var process in Process.GetProcesses()) 
       { 
        if (process.ProcessName.StartsWith("javaw")) 
        { 
         process.Kill(); 
        } 
       } 
       whShutdown.Set(); 
      } 
     } 
     Console.WriteLine("Done..."); 
     Console.ReadLine(); 
    } 

(注:我知道有问题,此代码周围(1)杀死不运行原型和(2)有没有代码,以大量的实例,同时启动应对Java进程,但这不是我的问题所在)。

在单个用户帐户下测试这个工作正常。我可以启动我的应用程序,然后启动原型,如果我启动应用程序的第二个实例,则第一个杀死原型的初始实例,然后第二个实例重新启动原型的另一个实例。

但是,如果我尝试从两个不同的用户帐户做到这一点,它会失败(无声)。如果我

  1. 开始我的应用程序的一个实例,它开始原型
  2. 切换用户
  3. 开始我的应用程序的一个实例,然后启动 原型没有我的应用从步骤1首先关闭现有 实例。

任何人都可以看到我的代码有什么问题吗?我应该如何在同一台机器上的几个同时用户会话中使用EventWaitHandle?

+2

事件对象在这里不是合适的对象,它遭受了无法解决的竞争条件。使用Mutex是样板,它有一个构造函数,返回* createdNew * bool,告诉你你的进程首先到达那里。 – 2012-08-08 12:30:55

+0

感谢Hans,这很有趣。在这种情况下,我认为我在比赛条件方面相对比较安全,因为第二款应用可以开始的机制需要时间。我开始使用两个互斥体,但交换事件,我会探索更多。 – dumbledad 2012-08-08 13:50:39

回答

0

是不是总是这样,在写了一个长问题后的几分钟内答案突飞猛进!

我在EventWaitHandle的名字中得到了斜线。这一个

new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppShutdownEvent", out createdShutdown, security) 

:例如更换构造函数调用

new EventWaitHandle(false, EventResetMode.AutoReset, @"Global\AaltoTokensAppShutdownEvent", out createdShutdown, security) 

修复我的问题。