Advertisement

Making a Form that doesn't freeze from Console Application

Started by October 01, 2014 04:15 PM
3 comments, last by Endurion 10 years, 3 months ago

Hi,

I have a console application that runs an 'infinite' main loop. Now I want to add a Form to it to serve as GUI.

My problem is, that if I run the Form first, and then start the main loop, it never reaches the main loop until the Form is closed because it freezes the thread.

If I do it the other way around, it never reaches the part where I run the form of course.

I've tried some other things, like using Form.Show() and then enter the main loop. But even though the form appears and the main loop works, the form becomes unresponsive.

Does anybody know another way to do this? I've tried some multithreading, but I can't seem to make communication between the Console app and the Form.

Thanks in advance,

Freek

A Windows form needs a windows message pump to work. Do you have one in your main loop?

(GetMessage/PeekMessage, TranslateMessage, DispatchMessage, etc)

You can also put the form on another thread, by calling Application.Run(your form here) from that thread.

Advertisement

What language, and what library? What is Form?

If you ever create a simple basic windows based application, you'll notice that shortly after the window has been created, you enter into an infinite loop that looks something like the following:


MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

This message loop calls GetMessage which blocks until a message arrives on the event queue. When an event arrives, the loop translates it's information into locale-specific values and then dispatches it to the appropriate receiving window's procedure (WNDPROC) handler.

The above code works well if you want your main UI thread to be dormant while it waits for incoming events from the operating system, but is far from ideal if you want to continue doing things in the loop. This is where PeekMessage becomes useful.


MSG msg;
while(!bExit) {
  while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    if(msg.message == WM_QUIT) {
      bExit = true;
    }
  }
  /* do your stuff here */
}

Whether you're doing console-based or window-based Win32 applications, the above loop will allow you to handle operating system events, allowing the window to remain responsive while also allowing you to perform whatever tasks you need to do for your main loop.

The biggest downside to the above is that if your stuff takes a bit of time per main loop iteration to complete, this can introduce input lag to your window message loop and could still make the window's title reflect "(Not Responding)". You'll need to experiment to see whether the above approach with PeekMessage will be sufficient for your needs or not. Chances are it should be more than sufficient at first but as your processing for stuff takes more and more time, you might find the need to split the two loops into two separate threads. The general idea here is that you'd use the first loop I presented above in conjunction with a bit of logic to capture input from the message loop, convert it into some data structure and dispatch it to a command queue that your second stuff thread inspects during each of it's loop iterations and processes input.

My suggestion is not to introduce any parallel threading to the mix until absolutely necessary as it does add a layer of complexity which can be hard to manage if you're not familiar with multithreading and shared data access requirements across multiple threads.

Since you do seem to use .NET: Application.DoEvents is an encapsulated message pump. Try to put it into your loop.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

This topic is closed to new replies.

Advertisement