2010-10-25 111 views
1

我正在編寫一個小測試應用程序來測試通信接口。通信接口是用C++(一個DLL)和使用C#的測試應用程序編寫的。通信接口進而與使用Windows消息傳輸和接收數據的低級硬件堆棧進行通信。爲了實現這一點,通信接口DLL創建一個不可見的子窗口,其父窗口是C#測試應用程序窗口。與硬件通話的順序如下:阻塞函數調用

  1. 初始化通信庫。這一步需要傳遞給低級堆棧的主窗口句柄和應用程序實例以進行Windows消息傳遞。

  2. 連接時使用的裝置地址

  3. 讀/寫

  4. 關閉

  5. 取消初始化通信庫。

現在,在第二步中,DLL創建一個不可見的窗口與低級硬件堆棧進行通信。由於第二步是阻塞呼叫,因此我希望我的用戶界面在這段時間內有所反應,以防連接需要很長時間。因此,我嘗試使用線程或BeginInvoke調用進行異步連接。但是我觀察到建立連接後,只要子窗口存在,應用程序窗口就會掛起。子窗口似乎阻止所有傳入主窗口的消息。這似乎是因爲子窗口是在另一個線程中創建的。

但我不想要連接在主線程中,因爲它掛起了用戶界面。

我會歡迎任何想法如何避免這個問題?提前致謝。

-Harish

+0

只是好奇爲什麼2是阻止呼叫?您的代碼是否繼續輪詢以查看設備是否已連接?作爲一種解決方案,爲什麼要創建子窗口 - 創建頂級消息窗口(http://msdn.microsoft.com/zh-cn/library/ms632599(VS.85).aspx#message_only)。 – VinayC 2010-10-25 13:31:36

+0

嗨維納,我不創建子窗口。我只使用開發者已經這樣做的DLL。我想內部的DLL有一個超時來知道連接是否完成。這是一個非常大的超時,因此對我的應用程序有阻塞作用。問題的一部分也是因爲通信堆棧提供商 – HIyer 2010-10-25 13:37:48

回答

0

與一個窗口句柄的所有通信都必須在該手柄上創建線程來完成。這可能意味着應該在輔助線程上完成對DLL的所有調用。

你可以嘗試以下方法:

  • 之前初始化DLL,啓動一個後臺線程;
  • 在該線程上,創建一個不顯示的WinForms窗口。你可以這樣做是這樣的:

-

public static Form BackgroundForm; 

[STAThread] 
static void Main() 
{ 
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 

    new Thread(new ThreadStart(Secondary)).Start(); 

    Application.Run(new MainForm()); 
} 

static void Secondary() 
{ 
    BackgroundForm = new Form(); 

    // Calling Handle creates the system HWND. You do not have to call Show 
    // or something similar on this Form to make the handle available or use 
    // Invoke or BeginInvoke. 

    var handle = BackgroundForm.Handle; 

    // Initialize the DLL here with the handle. 

    Application.Run(); 

    // Unintialize the DLL. 
} 
  • 然後,初始化你從後臺形式得到了手柄的DLL;
  • 當您需要對DLL進行調用時,請使用InvokeBeginInvoke來執行此操作;
  • 一旦要關閉應用程序,請通過InvokeBeginInvoke執行Application.ExitThread()

您在主窗體被阻止時看到的問題可能是因爲在DLL中創建的子窗口具有主窗體的句柄,因爲它是父窗口,但這只是一種猜測。這應該也可以使用這個系統來解決。

+0

謝謝彼得,我會檢查這個。這似乎是一件好事,嘗試。再次感謝。 – HIyer 2010-10-25 13:34:29

+0

不客氣。 – 2010-10-25 13:39:34