2010-10-25 180 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