Waiting on Mainthread while continuing processing on UI - c#

When working with console applications, Console.Readline relinquishes processing to the UI from the Main thread and only continues when an event, such as the pressing of the enter button is fired. How do I replicate this functionality (With a Window form as the UI in this case) in windows form application?

You cannot do this directly.
However, you can do it by calling Invoke, as I described here.

Use form.ShowDialog() instead of form.Show()
This will not stop the thread, but it will stop the user from doing other things in the UI until the window is closed.

Now that you have explained what you want to do...
It would be better to use a BackgroundWorker, keep the GUI active, but disabled and presenting a progress bar + cancel button, until done.

Related

Dialog hangs when called from event

Using the CoreScanner Driver provided by Motorola, I'm trying to write a small winforms application that uses a barcode scanner. I'm able to interact with the scanner just fine, and properly register a call back for the OnBarcodeEvent(). In this callback, I have a Dialog that opens and displays a screen that the user needs to fill in. Shortly after the dialog is opened (using Show()), the program hangs. If I use ShowDialog(), the dialog works, but the dialog is blocking the OnBarcodeEvent event.
My guess to what is happening, is that since the dialog is getting created on the event thread, there is a race condition occurring when using Show(). Since Show() is non-blocking, the thread continues on after displaying the dialog and then dies out. Meanwhile my dialog just lost it's parent and locks up? Like i said... my best guess.
How can I remedy the situation? That is, How do I write my dialog so that it can be created within a thread not hang?
In the event, you should launch a different thread that will create your dialog form and show the form on it. You need to block this thread till form is visible - this is possible either by ShowDialog or alternately use one of Application.Run overload.
Yet another option would be to show the form on the UI thread (i.e. main application thread) - to do that, you need to call Invoke method on your main form from the event code. The invoke call should take the delegate that will show your dialog form non modally.
I have some experience with Motorola/Symbol Handheld-Devices (MC9090) and I guess the SDK will be similar.
It's hard to say without seeing the code, but my guesses:
your common not-UI thread problem - so make sure you open your dialog using UI thread
the native Motorola-driver is crashing - no kidding, this happened a lot to me - in my case (compact-framework on a WinCE device) this would not freeze the program but the scanner will not work/receive any messages before restarting the device
In order to fix this you should seperate the showing/handling of user-dialog away from the event and make sure you call this on the UI-thread (Control.InvokeRequired / Control.Invoke).

Background work that perform UI change and modal dialog

I have a C#/WPF application that is going to perform a lot of actions, including UI modifications (it is loading a Macro), but I want to have a modal window with something moving telling to wait.
The load macro work must be performed in the main application thread, but how to I print the modal window as it must be non blocked by the macro loading but in the application thread because it is a UI thing.
Currently I put the LoadMacro in an BackgroundWorker in a Application.Current.Dispatcher.Invoke while displaying my waiting dialog. But it is not satisfying because the two fight each other to update the UI.
So how do I do it ?
You don't need to run the background worker from any dispatcher.
Load your modal window and then kick off the background worker having subscribed to it's ProgressChanged event. You can then ReportProgress on the background worker passing anything you like back to update the model window in the UserState property.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx

Creating an instance of a form in a BackgroundWorker

I want to create a new instance of a form in a BackgroundWorker. I've noticed that when I do this, the newly launched form freezes.
Why does this form freeze? How can I get around this?
It's freezing because you're creating the form in the wrong thread - there's no event loop running in the background thread.
You should only create or touch UI elements in the UI thread. BackgroundWorker provides some hooks for this, or you can use Control.Invoke/BeginInvoke.
When a form "runs" it needs to have a thread that runs the WndProc and handles incoming messages from Windows. What you should consider doing here is using the Application.Run() method to start up your form. This will do the necessary work to make sure the WndProc is running properly, and I belive you can call this from your Background thread if necessary.

C# console window problem with _getch()

I have embedded a console window within my Windows application form using ะก#
I have an application that runs in the console window. my c# project is a GUI to display the output of this and also to send parameters to it.
Most is working fine except when a call to _getch() is made from my GUI to the console window it tends to freeze up the whole system.
anyone got any ideas why this would happen?
I can post code if need be.
Thank you
Odds are that _getch() is a blocking call.
The _getch() function won't return until the user presses a typing key on the keyboard. If this function is called from your program's main thread then this will stall the UI thread. It won't pump the message loop, your UI freezes when it no longer processes input events nor paints the windows. After a couple of seconds Windows puts the ghost window in place with "Not Responding" in the title bar.
While calling _getch() from a background thread will solve the problem, that's probably not going to be convenient. You can use _kbhit() to check if a keystroke is available. Calling _getch() after _kbhit() returns true won't block. Probably not convenient either. Trying to pump the message loop while _kbhit() returns false would technically be a solution, if it wasn't for the message loop living in the wrong code.
Note that you can type Ctrl+S in the console window to pause output, Ctrl+Q resumes it again. You'll still block the UI thread but at least you'll do it knowingly.
What does _getch() do. You can start the call in another thread if its blocking the UI thread.

How to refresh screen so that closed forms actually disappear

I have multiple forms that popup during an intensive operation. For example, when a form popups asking user for something, and the user clicks OK, the form's graphics stay on the main screen, even though it is closed. How can I make it so that these graphics disappear completely?
I would recommend performing the heavy work in the background (using a BackgroundWorker for instance), so that the GUI thread is not blocked. That way, the forms will be able to peform screen updates while the work is going on.
It sounds like perhaps you are doing intensive processing on your main thread, which is the thread that processes events like painting windows. Instead you should spawn a separate thread for doing your computations/tasks so that your main thread can continue.
Alternatively you can call DoEvents() periodically while doing your processing to allow the form to refresh, but using DoEvents is kind of a cludge in my opinion.
You can call the Refresh() method on the main screen form, which will force a graphics repaint.

Categories