阻止函数调用

时间:2010-10-25 12:41:10

标签: c# c++ windows

我正在编写一个小测试应用程序来测试通信接口。通信接口用C ++(DLL)编写,测试应用程序用C#编写。通信接口又与低级硬件堆栈通信,后者使用Windows消息来发送和接收数据。为了实现这一点,通信接口DLL创建了一个不可见的子窗口,其父级是C#测试应用程序窗口。与硬件通信的顺序如下:

  1. 初始化通讯库。此步骤需要将主窗口句柄和应用程序实例传递给低级别堆栈以进行Windows消息传递。

  2. 使用设备地址

  3. 进行连接
  4. 读/写

  5. 关闭

  6. 取消初始化通信库。

  7. 现在,在第二步中,DLL创建了一个不可见的窗口,用于与低级硬件堆栈进行通信。由于第二步是阻塞调用,我希望我的UI在此期间能够响应,以防需要很长时间才能连接。因此,我尝试使用线程或BeginInvoke调用异步连接。但我发现连接建立后,只要子窗口存在,应用程序窗口就会挂起。子窗口似乎阻止所有传入消息到主窗口。这似乎是因为子窗口是在另一个线程中创建的。

    但我不希望连接在主线程中挂起UI。

    我欢迎有关如何避免此问题的任何想法?提前谢谢。

    -Harish

1 个答案:

答案 0 :(得分: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执行此操作以获取此背景格式;
  • 关闭您的申请后,请Application.ExitThread()Invoke进行BeginInvoke

您看到主窗体被阻止的问题,可能是因为在DLL中创建的子窗口具有主窗体的句柄,因为它是父窗口,但这只是猜测。这也应该使用这个系统来解决。