在Windows服务和Windows应用程序之间使用EventWaitHandles

时间:2015-04-12 04:03:15

标签: c# windows forms

我需要使用命名事件将信号从Windows服务发送到Windows控制台/ Forms应用程序。我创建了一个公共的NamedEvents类库,它具有创建事件的实现。

问题是我的Windows服务没有创建事件。如果我创建另一个Windows窗体应用程序(代替Windows服务)来创建一个事件,那么它工作正常。但是使用Windows服务它似乎不起作用。如果我在代码中遗漏了某些内容,有人可以告诉我

public static class NamedEvents
{
    public static EventWaitHandle OpenOrCreate(string name, bool  initialState, EventResetMode mode)
    {
        EventWaitHandle ewh = null;
        try
        {                
            ewh = EventWaitHandle.OpenExisting(name);
        }
        catch (WaitHandleCannotBeOpenedException)
        {                
            ewh = new EventWaitHandle(initialState, mode, name);
        }

        return ewh;
    }

    public static EventWaitHandle OpenOrWait(string name)
    {
        EventWaitHandle ewh = null;

        while (null == ewh)
        {
            try
            {
                ewh = EventWaitHandle.OpenExisting(name);
            }
            catch (WaitHandleCannotBeOpenedException)
            {
                Thread.Sleep(50);
            }
        }

        return ewh;
    }
} 

Windows服务代码:

public void SetSignalToClient()
{
    EventWaitHandle completedA = NamedEvents.OpenOrCreate("CompletedA", false, EventResetMode.ManualReset);                     
    completedA.Set();
    completedA.Close();
}

Windows窗体应用程序:

public Form1()
{
    InitializeComponent();
    new Task((o) => SubscribeToAsyncEvents(),
            new System.Threading.CancellationToken()).Start(); 
}

private void SubscribeToAsyncEvents()
{            
    while (true)
    {
        EventWaitHandle completedA = NamedEvents.OpenOrWait("CompletedA");
        completedA.WaitOne();
        if (textBox1.InvokeRequired)
        {
            textBox1.Invoke((MethodInvoker)delegate { textBox1.Text = "received"; });
        }
        completedA.Close();               
    }
}

1 个答案:

答案 0 :(得分:1)

MSDN article for CreateEvent中记录了这一点。为了在多个终端服务会话(也称为远程桌面会话)中使用事件对象,您必须创建一个全局事件对象,您可以通过启动带有前缀Global\的名称来完成此操作,例如{{ 1}}。

虽然文档没有提到它,但据我所知,.NET EventWaitHandle类将事件名称传递给CreateEvent不变。所以相同的机制应该有效。

Windows Services在会话0中运行,用户应用程序在会话1或更高版本中运行。因此,对于服务和用户应用程序进行通信,它们必须使用全局对象。

请注意,如果用户应用程序未以管理员身份运行,则该服务可能还需要显式设置事件对象的权限。