我需要使用命名事件将信号从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();
}
}
答案 0 :(得分:1)
MSDN article for CreateEvent中记录了这一点。为了在多个终端服务会话(也称为远程桌面会话)中使用事件对象,您必须创建一个全局事件对象,您可以通过启动带有前缀Global\
的名称来完成此操作,例如{{ 1}}。
虽然文档没有提到它,但据我所知,.NET EventWaitHandle类将事件名称传递给CreateEvent不变。所以相同的机制应该有效。
Windows Services在会话0中运行,用户应用程序在会话1或更高版本中运行。因此,对于服务和用户应用程序进行通信,它们必须使用全局对象。
请注意,如果用户应用程序未以管理员身份运行,则该服务可能还需要显式设置事件对象的权限。