tags:

views:

84

answers:

1

Hello,

I am writing a small test application to test a communication interface. The communication interface is written in C++ (a DLL) and the test application using C#. The communication interface in turn talks to a low level hardware stack which uses windows messages to transmit and receive data. In order to achieve this, the commuication interface DLL creates an invisible child window whose parent is the C# test application window. The sequence to talk to the hardware is as follows :

  1. Initialize the communication library. This step expects the main window handle and application instance which is passed to the low level stack for windows messaging.

  2. Connect using the device address

  3. Read/Write

  4. Close

  5. Deinitialize the communication library.

Now in the 2nd step, the DLL creates an invisible window to communicate with the low level hardware stack. Since the 2nd step is a blocking call, I want my UI to be responsive during this time in case it takes a long time to connect. Therefore, I try to connect asynchronously using a thread or a BeginInvoke call. But I observe that after the connection is established, the application window hangs as long as the child window exists. The child window seems to block all incoming messages to the main window. This seems to be because the child window gets created in another thread.

But I dont want want the connect to be in the main thread as it hangs the UI.

I would welcome any ideas on how to avoid this problem ? Thanks in advance.

-Harish

A: 

All communication with a window handle must be done on the thread this handle was created on. This probably means that all calls to the DLL should be done on the secondary thread.

You can try the following:

  • Before initializing the DLL, start a background thread;
  • On that thread, create a WinForms window you do not show. You can do this like this:

-

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.
}
  • Then, initialize the DLL with the handle you got from the background form;
  • When you need to do calls to the DLL, do this using Invoke and BeginInvoke to this background form;
  • Once it's time to shut down your application, do an Application.ExitThread() through a Invoke or BeginInvoke.

The problem you are seeing with the main form being blocked, is probably because the child window created in the DLL has the main form's handle as it's parent Window, but that's just a guess. This should probably also be solved using this system.

Pieter
Thanks Pieter, I shall check this. This seems like a good thing to try. Thanks again.
You're welcome.
Pieter