Why does Control.Invoke() calls PostMessage() instead of SendMessage()? - c#

Control.Invoke() calls PostMessage() and then waits until the UI thread finishes processing the message. So why it does not calls SendMessage() instead (which by default waits until the UI thread finishes processing the message).

Control.Invoke() is a dangerous method, many .NET programmers have deadlocked their program with it. It should be very strongly avoided because of this. Simple everyday operations like closing a window become perilous. You'll want to wait until a worker thread cannot invoke anymore since nothing good happens when the thread keeps running but the UI is gone. So you signal the thread with, say, AutoResetEvent and wait for it to complete.
Such a wait is very likely to deadlock your program when the thread is calling Invoke() at just the wrong time. The thread cannot complete because it is stuck in the Invoke() call, the UI thread cannot service it since it is stuck in the wait. A "deadly embrace", neither thread can make progress and your program will hang. Quite hard to debug since it is not predictable and doesn't happen often enough, only goes wrong when the thread calls Invoke at exactly the same time.
Breaking that deadlock requires knowing that an Invoke() call is in progress so it can be cancelled. It is not knowable when you use SendMessage(). The lock on which it blocks is hidden in the OS. I've recently posted an answer about the problems with SendMessage, everything you read there applies here as well.
So Microsoft did not implement it that way and they use PostMessage. They add an entry to the invoke queue, call PostMessage to wake up the UI thread so it goes looking through that queue. And specific to Invoke over BeginInvoke, they block on a ManualResetEvent in the queue entry, signaled when the UI thread completed the call to the delegate target.
Now they can do something to avoid the deadlock, when a window closes it looks through the invoke queue and cancels any that had that window as the invoke target. Or in other words, the lock that's invisible when you use SendMessage and causes deadlock now becomes visible and can be released to break the deadlock.

Related

Can Control.Invoke() be interrupted?

When calling Control.Invoke(), it blocks the calling thread until the message gets processed. I am wondering if I can break out of this block from another thread.
Note: I know that I can use Control.BeginInvoke(), but I am not asking about that.
No, you cannot.
The waiting thread decides the set of conditions that wake it.
If you want the option to interrupt a cross-thread call, you can use a ManualResetEvent, the WaitHandle from BeginInvoke, and WaitAny.
Note that if you do this and then wake from the wait using the event, it will not dequeue the cross-thread call. The worker thread simply won't wait for it any longer.
...if I can break out of this block from another thread
Control.Invoke() will run on the UI thread which is the main thread. If you kill it, you will exit the application.
To prevent the UI threading from blocking too long, you should only perform action in Control.Invoke() that is updating the control only. Anything else should be done else place.

C# - Compact Framework Windows CE - GUI Thread Blocks Higher Priority Threads

I am having an issue where I have a Windows CE compact framework Application written in C#, where I have the primary GUI thread set to normal priority and a communication thread set to above normal priority to get as close to pseudo real time performance. The issue I am having is within a button handler I run a loop to load config data from a file to the GUI before allowing it to be edited. This takes around 2-3 seconds to complete. While this blocking in the event handler is happening, my higher priority communication thread is being blocked. There are no locks are thread syncs in place. The communicatio thread has no dependencies on the GUI thread.
This is how I spawn my comm thread:
MbWorkerThread = new Thread(MbPollingThread);
MbWorkerThread.IsBackground = true;
MbWorkerThread.Priority = ThreadPriority.AboveNormal;
MbWorkerThread.Start();
It is an MTA application. Also, I have tried to use Thread.Sleep(1) in the GUI event handler to yield to the higher priority thread and it does not work. I also tried using signals to yield to the higher priority thread, and that does not work. The only thing that works is if I place Application.DoEvents() in the loop while loading config in the event handler. This of coarse whas just a test, as I do not want to sprinkle Application.DoEvents() throught my code to make it work since I know Application.DoEvents() is dangerous.
My understanding is that the primary GUI thread is a foreground thread, but a thread none the less. Also, I have made the communication thread a background thread just to allow it to be killed when the primary thread is exited.
I have tried everything, I have search the Internet endlessly before asking this question.
Any help will be greatly appreciated.
P.S. - I though about a form timer but I know it runs in the GUI thread so that would not help. I though about another thread but I really did not what to marshall GUI updates via Invoke.
Your program starts in Main(), where you typically call Application.Run( new MyForm() ). Application.Run() implements the standard Windows Message Pump, which deals with messages from the OS and other applications, including user input, inter-process communication, repaint requests, etc.
GUI events, like Button click, are dispatched via this thread. If you perform long-running work in an event handler, other messages are not being processed.
Application.DoEvents() blocks the calling thread, and waits for all pending messages to be processed. If DoEvents helps your communication thread when Sleep(1) did not, then I suspect there is a dependency between your communication thread and the GUI/Message Pump thread.
Even if this is not the case, it is not a good idea to block the GUI thread. Move your file loading into the background with ThreadPool.QueueUserWorkItem() and marshal the results back to the UI at the end with Invoke or BeginInvoke.
BeginInvoke instead of Invoke fixed the issue. Thanks for the replies.

TCPlistener.BeginAcceptSocket - async question

Some time ago I have payed to a programmer for doing multithread server. In the meantime I have learned C# a bit and now I think I can see the slowndown problem - I was told by that guy that nothing is processed on the main thread (Form) so it cannot be frozen..but it is.
But I think that altough BeginAcceptSocket is async operation, but its callback runs on the main thread and if there is locking, thats the reason why the app freezes. Am I right?
Thanks
this.mTcpListener.BeginAcceptSocket(this.AcceptClient, null);
protected void AcceptClient(IAsyncResult ar)
{
//some locking stuff
}
No, AcceptClient() will not run on the main thread.
Better show some of the 'locking stuff'.
The Begin/End asynchronous IO methods use ThreadPool threads to execute the callback delegate, unless the operation can be completed instantly; in which case it executes synchronously on the calling thread.
From Calling Synchronous Methods Asynchronously:
Pass a delegate for a callback method to BeginInvoke. The method is executed on a ThreadPool thread when the asynchronous call completes. The callback method calls EndInvoke.
The callback should not often be occurring on the GUI thread.
If the application window becomes unresponsive, it may be as a result of excessive invoking of methods on the GUI thread - usually to update controls.
I made small winapp test and the result is that even if 'AcceptClient' method is declared in the same class than this delegate is invoked from other thread than main winform app thread, and thus NO blocking is there.
Anytime that your code gets a lock and then does something you have a candidate for a bottleneck, however, the thread that calls BeginAcceptSocket won't be blocked and can continue to do work until the callback event happens. It won't execute the callback handler until then so, in your example, none of the locking will occur until it has been contacted by a client. It still may be hanging up in the accept code if whatever it does at that point takes time or gets delayed due to communication issues, but it's hard to tell from your code sample if that's the case.
AcceptClient(IAsyncResult ar) callback may be completed synchronously.
I guess if BeginAccept encounters that there is a new client it can execute callback method synchronously.
To be sure you have to stop your application under debugger when it froze and see what Main (event) thread is doing.
Generally it is better to have separate thread for doing any I/O.

AutoResetEvent and COM Objects

I've noticed that AutoResetEvent completely freezes the message loop (sometimes) when in the middle of a WaitOne() call, effectively even blocking the signal message.
IE:
(UI) New thread spawned
(UI) Code calls WaitOne(); timeout: 10s
(T2) Thread opens device, calls Set()
(UI) WaitOne blocks message loop
(UI) WaitOne timeout elapsed, code execution continues
(UI) Main window receives signal and continues (but WaitOne failed)
Any ideas?
EDIT: added UI/T2's to specify threads. Also, I'm trying to turn a 3rd party library to synchronous. Opening devices involves an Open() call that in turn spawns an OpenOK or OpenFailed event, I'm trying to make a bool Open() call that returns true/false depending on which event was spawned.
... effectively even blocking the signal message.
You can't "block a signal" from being sent, you can only prevent the other thread from getting to the point of setting the event. Wait handles do not require a message pump at all.
The only thing I can think of may be that the COM object in question is tied to the UI thread. Accessing the COM object may be attempting to invoke back from T2 to the UI thread which is waiting for T2 to do something (deadlock). To see if this is indeed the problem make sure you are not creating or accessing the COM object on the UI thread.
This is the result of a race condition. The problem is that step 3 might be happening before step 2 because they're on different threads. Because you're using an AutoResetEvent, by the time WaitOne is called, the event is already reset.
Because of this problem, whenever possible, I generally try to avoid AutoResetEvents in favor of ManualResetEvents.
The order of events with a ManualResetEvent would be (I've listed event 2 as 2a and 2b to demonstrate that their order of operation is not guaranteed):
New Thread Spawned
a. Original thread calls WaitOne(); b. New thread calls Set();
Original thread wakes up.
Original thread calls Reset();
You might find this SO post on "Waiting on the mainthread while continuing to process"
Also checkout Calling Synchronous Methods Asynchronously from MSDN

Thread, abort and wait

I am aborting a thread (will be threads soon enough) and the problem is i need to stall until all threads have been aborted.
After doing the Thread.Abort(); I thought of using the Thread.Join() to wait until its been fully aborted. However that doesnt work. It just waits forever. How can i abort each thread and wait until its done before continuing?
Additional information: If your curious why - in this case I am closing a window, I pass a delegate func into the thread which it calls when its done (or aborted). If I dont stall then the window will close and the function will call invalid handles/objs. I can easily use the same method, stick a flag in and loop & sleep until all flags are set but that doesnt feel right.
I've learnt from many years experience with threads that there are a couple of rules that, if followed, make life a lot easier.
The one pertinent to this question is:
let threads control their own resources, including their lifetime.
I wouldn't abort a thread, I'd simply set up a communications method between the threads creator and the thread itself to signal the thread to terminate, and then let the thread itself shut down.
This method can often be as simple as a write-by-creator/read-by-thread flag which controls the threads main loop. If the thread has long running tasks while in the loop, you should also check periodically.
Then the creator thread should just join until the thread exits. Properly designed, you can set an upper limit to the time this will take.
Use a synchronisation object such as an Event. For example, each background thread has an Event associated with it. When the thread is terminating, it signals the Event. The main thread does a WaitHandle.WaitAll on the set of Events, and proceeds only when all Events are signalled.
Be warned that if there is a chance that the background threads will take a long time to terminate, blocking the main thread while waiting for them would create a bad user experience. So if this is the case, you may want to hide the window before blocking. Also, you'll want to test what the impact of this is on your callback delegate -- if the UI thread is blocked in a wait, will it be able to handle your delegate?
Might not a better design be not to call the delegate if the thread is being killed due to the window closing? Just have the main thread tell the background threads why they are terminating and have them skip the callback if the reason is "window closing." (This assumes that you are communicating with the threads, as Pax rightly recommends, rather than just calling Abort.)

Categories