Can a thread own other handles? - c#

http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
Executes the specified delegate on the thread that owns the control's
underlying window handle.
According to the MSDN article, a thread can own other handles.
My best guess, is that the thread is some special super kernel object, with a handle that other handles can refer too?
like:
Handle | Thread-Handle-Reference
3201 | 20
4882 | 20
4827 | 7

In these terms, yes.
Basically, behind the scenes of the Windows GUI is a "message loop", which is a two-way communication between the Windows OS (which knows about the mouse, keyboard and other input hardware) and your program (which doesn't need to know the specifics, but does need to be responsive to user input within your app based on these input devices). There is a thread in your program (the main program execution thread, usually) that maintains this loop, listening for messages coming into the program from Windows, and parsing and passing messages to the various GUI controls and other code objects. This "GUI messaging thread" knows and maintains references to all the window handles of all GUI objects in your program; it must, because if it doesn't, it cannot pass messages to them and will not be listening for messages from them.
It is generally a bad idea to try to do something to a GUI control instance from outside the thread that is connected to the message loop. By doing so, it is possible for the control or sub-controls owned by the control to become detached from the message loop, or to never be attached in the first place. The "GUI message thread" then no longer knows about that control, and is no longer passing messages to or from it. Those controls become "rogue"; neither the program nor Windows can tell the control to move, redraw itself, or go away. The only thing Windows can do at that point to "control" the window is to shut down the process that owns it, thus terminating your entire program.
To avoid this, GUI controls have a special method "Invoke" (and an asynchronous cousin "BeginInvoke") designed to be used from outside the GUI messaging thread. These methods basically send a message from the window to itself through the Windows message loop that causes the main GUI thread to execute the delegate specified in the Invoke call. By doing so, any new GUI objects created within or as a result of that code will be known to the main GUI thread.

A custom thread can own handles when the handle is created in the custom thread. Actually i don't think that you can switch the owner of the handle. Sharing should be not possible too.
A thread can own multiple handles at once.

Every window is owned by the thread which created the window. Many window operations can only be performed on that thread, so it's important to have a mechanism to ensure that code is executed on the window's thread.
Forms.Invoke is one such mechanism.

Related

How to make 2 forms on 2 separate threads in C# winform application

I am developing an interface in my C# 4.0 winform application, to fire some sms in bulk. Each message content is different so that I have to fire messages one by one. I have a form from where the end user can shoot smss, it may be more than a thousand.
I want to manage a queue. If the user shoots a sms then it will be submitted to the queue and the queue will send sms one by one.
So I have to create a form to manage the queue. The problem is that I want my application to work normally and in the background the queue sends sms.
So how can I achieve this task? I have tried BackGroundWorker, but I don't know how to maintain a separate thread with a form.
All forms must be on the UI thread. The sending of the SMS should be performed by the BackgroundWorker.DoWork event. The updating of the form is then done by BackgroundWorker.RunWorkerCompleted event.
The UI thread is main thread of the application for SWF (winforms)
If you are using C# 4.0 or above, you may also want to investiage the Take Parallel Library (http://msdn.microsoft.com/en-us/library/dd460717.aspx). But I would first get BackgroundWorker implementation to work. Then use TPL to send simultaneous SMS. Could really speed things up.
you have to create one thread (called worker thread) which runs for the life your application.
you have to have a queue or even better a concurrent queue http://msdn.microsoft.com/en-us/library/dd267265.aspx
the worker thread wait when an item (sms) appears in the queue, takes that item and do its work.
the UI is completely decoupled from that work.
this is most basic use of the class Thread.
Background worker is least suitable solution. obviously you can use a washing machines to build a house but most people use bricks.
You can start Thread then create new instance of form on it (with no parent) and then start message loop (such code located in Main method of project's template).
Remember, any form (generally any GDI object) can be used only on thread that creates it. E.g you can't create child form on another thread, then parent's. Every GUI thread must run message loop.

Creating a Form and using Form.ShowDialog on a background thread

Using Winforms,
If I'm on a thread that is not the "main" ui thread can I safetly
Create a Form,
Call ShowDialog on that form
It seems like I would be obeying the rule of:
Winforms controls must be modified on the thread they were created in.
From some of the reading I've done it seems like ShowDialog will create its own message pump so that I don't need to worry about the Form being created on a thread that already has a message pump.
The background of the question is that I get a callback where I'd like to display some Winforms UI, but I don't have access to any other UI that I could use to Invoke to the main thread.
That's roughly correct, albeit that it is pretty important that you call the thread's SetApartmentState() method to switch the thread to STA. Important for many UI operations, including the clipboard, drag and drop and the shell dialogs. And that you usually have a crummy Z-order problem when the form that you create on the thread is not in the foreground and hides behind another window. Or has the nasty habit of actually do move in the foreground when the user doesn't expect it and grab a mouse click or keystroke unexpectedly.
These are hard problems to fix, they do make your app flaky. There's no good reason to not have a reference to invoke to, you can also pass it to the class some way some how. You've always got Application.OpenForms[0] to fall back on, if really necessary.
Yes, you can do that, but if you want the dialog to actually act like a modal dialog (i.e., block the parent Window, which I assume you want since you are calling ShowDialog) then be prepared to be disappointed.
What problem are you actually trying to solve here. It sounds like you want a modal dialog that doesn't block, which is a bit strange. If you explain the problem at hand there may exist a solution you have not yet considered.

Open new form from inside each thread?

I'm using the following code to open a new form (that is for user input) in my function:
Form4 f4 = new Form4();
f4.mainform = this;
f4.get_Text(matchString);
f4.ShowDialog();
It's working perfectly when not threading, but when I try to run the function on two threads I only get 1 form popup. How can I adjust it so that it will support more than one thread?
You can open a form from any thread, you just need to start a message loop on the new thread, such as:
Application.Run(f4)
The Run method will not return until the form is closed. It can cause issues, though, so you need to be careful and know what you are doing. Unless it's a real pain to do, I would sooner consider redesigning your code to be more asynchronous. For instance, you could create a event handler method to listen for the form's closing event.
The WIN32 Message pump runs on one thread -- the GUI thread. As soon as you .ShowDialog(), the c# stops until the user closes the dialog. Even if you use .Show() to avoid a "stop and wait for the user to push ok", you still must handle all GUI events on the GUI thread by .Invoke()ing to the GUI thread.
The way to support multi-threaded-ness is by doing non-GUI work on alternate threads.
ShowDialog does pump messages so it would technically work on a separate thread without needing a dedicated message loop. However, what you currently have looks like a recipe for disaster because that form appears to hold a reference to another form via f4.mainform = this and it is presumably trying to access it. You simply cannot do this without littering (and I mean that literally) your code with a bunch of Invoke or BeginInvoke calls.
Furthermore, running UI forms on a thread other than the main UI thread generally does not work well. There are a few obscure problems you can run into. For example, since there would be two UI threads in play it is possible to have 2 active modal dialog boxes open. One might be hidden behind the other and the end user would not see it. This reason, among others, is why it is not generally recommended to use more than one UI thread.
My advice is to figure out a way to make this work with a single UI thread. Your life will be simplier if you do.

Using Invoke with a UI element that extends Application Context?

I have a taskBarIcon element extending Application Context from which my entire UI is designed. This is because the original functionality of the application was to run a background process and simply provide the icon as a confirmation that the app was running.
However, I am now adding additional functionality in the form of a menu that may be accessed by right clicking the icon, and since the core functionality is running on one thread, and the icon on the main thread, I am having issues accessing the icon in the simple case of needing to display a notification bubble. There are no other points at which the two threads may be accessing the same memory, so synchronization is not really an issue.
I am used to Java, in which this process is far simpler. I've read the articles I can find regarding the Invoke-Delegate dance that C# requires, but none are specific to an object extending Application Context. My current implementation is far too unpredictable to be production safe.
My question is this: How do I send the message to the other process to display the notification bubble, without disturbing the accessibility of the menu? Specifically, a simple example with a UI class extending Application Context and a class on a separate thread calling the invoke method would be very helpful.
I really appreciate any help!
badPanda
You could just as well use a SynchronizationContext object that you assign to SynchronizationContext.Current on the same thread that you create the notification bubble. You would then pass your SynchronizationContext object into whatever component the menu is on and it would use context.Send(....) to send a message. Or, if you have access to the notification bubble component or the form it's on, you could do form.Invoke((MethodInvoker)delegate {....});

Is there an 'Application.DoEvents' at the form level?

I currently have an application that spawns multiple instances of a single win form. Each instance of the form has a timer which updates a number of controls and some of the properties of the form itself at rate of approx 1 tick/sec. Once the application reaches a certain number of forms it stops painting the 'updates' that occur within the timer ticks.
I want to hold the UI thread at the bottom of the timer and allow the form to repaint without calling Application.DoEvents (my understanding is that Application.DoEvents() handles all pending window messages across the application (which could include other timers 'ticks'? - not sure) when all I want it to process is the redrawing of the form now that a number of the controls have been updated).
It's not clear to me why you want to call DoEvents at all. Why not just let the window repaint itself appropriately? What's wrong with the way it behaves at the moment?
Calls to DoEvents usually indicate that something should be in a background thread - in your case it sounds like it might actually just be that you've got too many events going on. If your GUI is so complex that it can't redraw itself in a second, it sounds like that's probably a design issue with the UI itself.
If you just want the form or a specific control to redraw itself, just call Control.Refresh on the form/control in question.
That being said, this is usually (like Application.DoEvents) a sign that a redesign is in order. If you have long running processes like this, it's a much better idea to push the work into a BackgroundWorker, which will make the actual computational work run in a background thread, and prevent the UI from becoming unresponsive.
There are three categories of Windows messages that are dispatched by the message loop and a call to Application.DoEvents(). First are messages that are sent with SendMessage(). They are important, they need to be dispatched right away because there is some other program waiting on the result of the SendMessage() call. They are not put on the message queue, Windows calls the window procedure directly.
Then there are messages that are put on the message queue with PostMessage(). They can wait, they are merely notifications. All of the keyboard and mouse messages fit that category.
Then there are the low priority messages, WM_TIMER and WM_PAINT. They only get dispatched when there's nothing else to do, no SendMessage is pending and the message queue is empty.
Sounds like you got yourself into a situation where you starving Windows so badly that it can't get around to dispatching those low priority message anymore. Probably neither getting timer Ticks nor Paint events anymore. Calling DoEvents only once a second will certainly do that. This is bad, your program is now affecting the operation of other programs as well. You'll have to fix that. Do so by re-architecting your app so you no longer depend on DoEvents.
My 2c:
Having a timer in each form is going to slow down performance to a crawl. Each window at each second interval is going to request the application to switch to that window's "context" and execute some code. That whole switch is likely longer than your code actually takes to run. Couple that with the likely fact that all of your forms are in the same "context".
Instead consider something like this if possible:
List<MyForm> listofmyform;
Timer t = new Timer()
t.tick += delegate
{
foreach(MyForm thisform in listofmyform)
thisform.DoUpdate();
}
This only uses one timer to update all of your forms, only requires one "context switch" and will likely cure some performance problems you're having.

Categories

Resources