謝謝大家的建議。理查德& overslacked,你在評論中提供的鏈接是非常有幫助的。此外,我不必允許該服務與桌面進行交互,以便通過Application.Run手動啓動消息泵。顯然,如果您希望Windows自動爲您啓動消息泵,您只需要允許該服務與桌面進行交互。
每個人的薰陶,這裏是我終於實現了手動啓動消息泵該第三方API:
internal class MessageHandler : NativeWindow
{
public event EventHandler<MessageData> MessageReceived;
public MessageHandler()
{
CreateHandle(new CreateParams());
}
protected override void WndProc(ref Message msg)
{
// filter messages here for your purposes
EventHandler<MessageData> handler = MessageReceived;
if (handler != null) handler(ref msg);
base.WndProc(ref msg);
}
}
public class MessagePumpManager
{
private readonly Thread messagePump;
private AutoResetEvent messagePumpRunning = new AutoResetEvent(false);
public StartMessagePump()
{
// start message pump in its own thread
messagePump = new Thread(RunMessagePump) {Name = "ManualMessagePump"};
messagePump.Start();
messagePumpRunning.WaitOne();
}
// Message Pump Thread
private void RunMessagePump()
{
// Create control to handle windows messages
MessageHandler messageHandler = new MessageHandler();
// Initialize 3rd party dll
DLL.Init(messageHandler.Handle);
Console.WriteLine("Message Pump Thread Started");
messagePumpRunning.Set();
Application.Run();
}
}
我必須克服一些障礙得到這個工作。一個是你需要確定在執行Application.Run的同一個線程上創建表單。您也只能從同一個線程訪問Handle屬性,所以我發現在該線程上簡單初始化DLL也是最簡單的。據我所知,無論如何,它期望從GUI線程初始化。
另外,在我的實現中,MessagePumpManager類是一個Singleton實例,因此只有一個消息泵運行於我的設備類的所有實例。如果你在你的構造函數中啓動線程,確保你真的懶 - 初始化你的單例實例。如果從靜態上下文啓動線程(例如,私有靜態MessagePumpManager實例= new MessagePumpManager();),運行時將永遠不會切換到新創建的線程,並且在等待消息泵啓動時會死鎖。
看看這個主題,它可能會證明有幫助:http://connect.microsoft.com/VisualStudio/feedback/details/241133/detecting-a-wm-timechange-event-in-a-net-windows-service – overslacked 2010-03-14 22:34:12
@overslacked,它的確如此。它說明了如何做到這一點。 – 2010-03-15 05:36:20
@overslacked我知道這是一個老問題,所以毫不奇怪,MS Connect鏈接不再起作用。但是,由於該鏈接的內容似乎對這裏的討論至關重要,所以我想知道是否有新的鏈接可用。很抱歉引起麻煩! – Sabuncu 2015-09-03 17:57:11