Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何向windows服务发送自定义消息?_Windows_Multithreading_Delphi_Service_Message - Fatal编程技术网

如何向windows服务发送自定义消息?

如何向windows服务发送自定义消息?,windows,multithreading,delphi,service,message,Windows,Multithreading,Delphi,Service,Message,我已经实现了一个WindowsXP服务应用程序,它启动了几个工作线程。 我需要从其中一个线程将自定义消息发送回服务。 如何做到这一点?一个选择是使用(阅读示例)。我同意TOndrej的观点,共享对象应该足够了 另一方面,您可以使用我的IPC(),它在服务内部运行良好。它易于使用,面向消息,所以您不需要知道命名管道是如何工作的,而且速度非常快。服务器部分还使用线程池,因此无需等待处理某些内容。您可以使用火灾后遗忘场景 或者,如果您认为稍微重新设计一下就可以了,您可以尝试OmniThreadLibr

我已经实现了一个WindowsXP服务应用程序,它启动了几个工作线程。 我需要从其中一个线程将自定义消息发送回服务。
如何做到这一点?

一个选择是使用(阅读示例)。

我同意TOndrej的观点,共享对象应该足够了

另一方面,您可以使用我的IPC(),它在服务内部运行良好。它易于使用,面向消息,所以您不需要知道命名管道是如何工作的,而且速度非常快。服务器部分还使用线程池,因此无需等待处理某些内容。您可以使用火灾后遗忘场景

或者,如果您认为稍微重新设计一下就可以了,您可以尝试OmniThreadLibrary,它已经内置了所有消息传递功能,并且是为类似这样的任务而设计的

编辑

好的,可能最干净的方法,没有任何重新设计,就是有一个公共对象列表,它由一个关键部分保护。工作线程正在列表中添加需要处理的对象。当添加和对象时,工作线程发出事件信号。然后,您有一个对象处理线程,该线程正与WaitForSingleObject一起等待此事件。一旦向列表中添加了某些内容,事件就会发出信号,处理线程只处理它在列表中找到的所有对象。然后它再次等待。您所需要做的就是保护对公共列表的访问

简化后的代码如下所示:

工作线程

ObjectList.Add(MessageObject);
SetEvent(FEvent);
加工线程

while not Terminated do
begin
  WaitForSingleObjest(FEvent, INFINITE);
  // process all the objects
end;

正在创建“仅邮件”窗口:

procedure TMyService.MessageQueueDispatch(var Message: TMessage);
begin
  Dispatch(Message); //Delphi default dispatcher for TMyService
end;

procedure TMyService.SomeKindOfOnCreate;
begin
  MessageQueue := AllocateHWnd(MessageQueueDispatch);
end;
摧毁:

procedure TMyService.SomeKindOfDestroy;
begin
  CloseHandle(MessageQueue);
end;
现在,您可以像处理表单消息一样处理消息:

TMyService = class(TService)
...
protected
  procedure HandleMyMessage(var msg: TMsg); message WM_MY_MESSAGE;
end;
procedure TMessageService.HandleServiceMessage(var Msg : TMessage);
var
  Handled: Boolean;
begin
  Handled := True;
  if Msg.Msg = WM_MYMESSAGE then
    Beep
  else
    Handled := False;
  if Handled then
    Msg.Result := 0
  else
    Msg.Result := DefWindowProc(WHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;

Delphi Dispatch()处理程序将负责调用该函数。

感谢您的帮助。下面是我如何解决这个问题的:

在服务类定义中:

  WHandle: HWND;
protected
  procedure HandleServiceMessage(var Msg: TMessage); virtual;
在ServiceExecute方法中:

  WHandle := AllocateHWnd(HandleServiceMessage);
  MyThread := TMyThread.Create(true);
  MyThread.HndMain := WHandle;
  MyThread.Resume;
  while not Terminated do ServiceThread.ProcessRequests(True);
  DeallocateHWnd(WHandle);
end;
  PostMessage(HndMain,WM_MYMESSAGE,0,0);
在ServiceStop方法中:

  MyThread.Terminate;
以及处理消息的方法:

TMyService = class(TService)
...
protected
  procedure HandleMyMessage(var msg: TMsg); message WM_MY_MESSAGE;
end;
procedure TMessageService.HandleServiceMessage(var Msg : TMessage);
var
  Handled: Boolean;
begin
  Handled := True;
  if Msg.Msg = WM_MYMESSAGE then
    Beep
  else
    Handled := False;
  if Handled then
    Msg.Result := 0
  else
    Msg.Result := DefWindowProc(WHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;
在MyThread.Execute方法中:

  WHandle := AllocateHWnd(HandleServiceMessage);
  MyThread := TMyThread.Create(true);
  MyThread.HndMain := WHandle;
  MyThread.Resume;
  while not Terminated do ServiceThread.ProcessRequests(True);
  DeallocateHWnd(WHandle);
end;
  PostMessage(HndMain,WM_MYMESSAGE,0,0);

工作正常。

您的工作线程是服务应用程序的一部分,因此不清楚您要做什么。我的印象是,您需要在线程之间传递一些数据,这可以通过简单地保留对数据结构的引用并锁定线程安全性来实现。根据您的意图,主服务线程可能更容易轮询工作线程的状态。你能提供更多的细节吗?我会尽力解释得更好。我的服务应用程序在其OnStart事件中创建两个线程。它还创建一个对象列表(对象有自己的函数和属性)。现在,两个线程中的一个轮询串行端口以获取新数据,并且需要将此数据(或超时)发送到对象列表中的一个对象,但是我需要在不中断其执行的情况下执行此操作。因此,当串行端口上的数据可用时,我想向主服务线程发送一条消息。这个主服务线程无法将数据发送到对象。我知道一个可能的解决方案是在服务类中创建一个只显示消息的窗口,但我不知道该怎么做。我没有时间重新设计。除了这一部分之外,整个应用程序都工作得很好。我只需要从主服务线程运行内部对象函数,而不是从工作线程运行。然后使用我的IPC解决方案或实现我在编辑中提出的建议。使用这种方法,我最好创建另一个线程来查看消息,并将其分派到正确的对象。我将查看IPC ToAllocateHwnd()不是线程安全的,不应在主线程之外调用。TService在它自己的工作线程中运行。