Hosting Controls over Multiple Threads in .Net - c#

I have a problem and after three days I still can not find a answer.
I am creating a usercontrol. This control has two controls hosted on it. One is an edit field and the other is a margin that will hold line numbers and other user added stuff.
What I am trying to do is instantiate these to separate controls in their own threads and perform all tasks on these threads eg painting and updating. The usercontrol thread will simply filter messages and direct same to the correct control. I will be doing this by overriding the WndProc method.
Doing all the message stuff I am fine with however how do I instantiate the controls. Once the thread that creates these controls finishes wont the threads die and the controls became inaccessible. Sorry no code at the moment, I tend to do a lot of research before any coding but I can't seem to find anything that can be of help.

This is not going to work very well. All UI elements (forms, controls, etc.) have thread affinity requirements that dictate that they can only ever be accessed from the thread that created them. Trying to embed a control hosted on one thread in another control from another thread is an effort in futility. Even if you can get it work (and use the term "work" loosely here) the results may be unpredictable at best. You need to rethink your approach. It would be much better to host all of the controls on the same thread and then shuttle off any time consuming operations to a worker thread. Remember, keep the worker thread busy with non-UI related operations only. Once the operation is complete then you can marshal over the results to the UI thread where it can dispatched appropriately to the controls.

Related

Why only the thread that created UI control can access it [duplicate]

I know that if I am modifying a control from a different thread, I should take care because WinForms and WPF don't allow modifying control's state from other threads.
Why is this restriction in place?
If I can write thread-safe code, I should be able to modify control state safely. Then why is this restriction present?
Several GUI frameworks have this limitation. According to the book Java Concurrency in Practice the reason for this is to avoid complex locking. The problem is that GUI controls may have to react to both events from the UI, data binding and so forth, which leads to locking from several different sources and thus a risk of deadlocks. To avoid this .NET WinForms (and other UIs) restricts access to components to a single thread and thus avoids locking.
In the case of windows, when a control is created UI updates are performed via messages from a message pump. The programmer does not have direct control of the thread the pump is running on, therefore the arrival of a message for a control could possibly result in the changing of the state of the control. If another thread (that the programmer was in direct control of) were allowed to change the state of the control then some sort of synchronization logic would have to be put in place to prevent corruption of the control state. The controls in .Net are not thread safe; this is, I suspect by design. Putting synchronization logic in all controls would be expensive in terms of designing, developing, testing and supporting the code that provides this feature. The programmer could of course provide thread safety to the control for his own code, but not for the code that is in .Net that is running concurrently with his code. One solution to this issue is to restrict these types of actions to one thread and one thread only, which makes the control code in .Net simpler to maintain.
.NET reserves the right to access your control in the thread where you created it at any time. Therefore accesses that come from another thread can never be thread safe.
You might be able to make your own code thread-safe, but there is no way for you to inject the necessary synchronization primitives into the builtin WinForm and WPF code that match up with the ones in your code. Remember, there are a lot of messages getting passed around behind the scenes that eventually cause the UI thread to access the control without you really ever realizing it.
Another interesting aspect of a controls thread affinity is that it could (though I suspect they never would) use the Thread Local Storage pattern. Obviously if you accessed a control on a thread other than the one it was created on it would not be able to access the correct TLS data no matter how carefully you structured the code to guard against all of the normal problems of multithreaded code.
Windows supports many operations which, especially used in combination, are inherently not thread-safe. What should happen, for example, if while one thread is trying to insert some text into a text field starting with the 50th character, while another thread tries to delete the first 40 characters from that field? It would be possible for Windows to use locks to ensure that the second operation couldn't be begun until the first one completed, but using locks would add overhead to every operation, and would also raise the possibility of deadlock if actions on one entity require manipulation of another. Requiring that actions involving a particular window must happen on a particular thread is a more stringent requirement than would be necessary to prevent unsafe combinations of operations from being performed simultaneously, but it's relatively easy to analyze. Using controls from multiple threads and avoiding clashes via some other means would generally be more difficult.
Actually, as far as I know, that WAS the plan from the beginning! Every control could be accessed from any thread! And just because thread locking was needed when another thread required access to the control --and because locking is expensive-- a new threading model was crafted called "thread rental". In that model, related controls would be aggregated into "contexts" using only one thread, thus reducing the amount of locking needed.
Pretty cool, huh?
Unfortunately, that attempt was too bold to succeed (and a bit more complex because locking was still required), so the good old Windows Forms threading model --with the single UI thread and with the creating thread to claim ownership of the control-- is used once again in wPF to make our lives ...easier?

Legacy code performance issue - Create UIControl on second thread, not only alter it

I inherited a winforms app. It uses a third-part-closed control that renders documents and photos... It has only sync methods for opening a document. The problem is that my clients are dealing with really big documents (in the area of 2GB!!!) and opening these docs really "block" the UI thread... which is bad...
Common sense would make you think "Just off-load it to a background thread" but the question is "HOW"! See, to alter the control (because calling "Open" causes it to be altered) I need to Invoke it, and that causes the code to run o UI thread again... locking it up...
So I turned the table upside down. What if instead of creating the control on the main thread and passing it to a background thread for processing, I could create the control on the background thread, load it up (avoiding this way the cross-thread exception) and, when done, feed it to the main thread?!?
Right now what I need is to know how to definitively handle a control to another thread, and not only temporally...
I'm not sure if this is possible but you could try to:
create a new form on a secondary thread (this form will host your fancy control)
load the document from this secondary UI. It will be blocked but you can hide it and only display a
loading message on the main UI.
when the job is finished transfer the 'work' to main UI and main thread.
It's just an idea.
What you are asking to do is impossible. A Winforms control's thread affinity is determined when that control is created, and it cannot be changed.
The best solution is to not use that control. I doubt there's anything it does that cannot be implemented correctly and competently by someone else.
If you are okay running a completely different window in a second STA thread, then that would be the next best thing. That particular window will still be frozen while the document loads, but at least your main UI would still be okay. Note that you should not try to mix and match controls from different threads in the same window; that will lead to all kinds of headaches.
Finally, as a complete hack, you might consider going ahead and calling this Open() method in a background thread in spite of the control being owned by the main UI thread. On the admittedly shaky assumption that the only time that control will actually attempt to access the UI component itself would be at the very end of the Open() method operation, you can go ahead and catch the InvalidOperationException that is thrown, and use that as your signal that the document loading has completed. Then just invalidate the control in the main UI thread.
I'd give the odds of this last suggestion working no better than 50/50. It will depend on what the control actually does with the loaded data, and if it's some kind of composite control where it's relying on actually taking the result of its loading and copying that to a control as part of the Open() method, that part might fail and the control would not wind up properly initialized.

How can I balance the load of a UI across several processor cores?

I am running a C# winform application that shows huge number of statistics and charts frequently. This application consist of multiple forms, each form has different output. When I open the task manager and check out the cpu usage, I find that only one core out of my eight cores is over loaded and the rest are doing nothing!
Is there a way, for example, to assign each number of forms to a core. I need to improve the perfomance.
What I am looking for is to multithread my winforms such that each form would have a different thread that is running on a different core. Is that possible ?
The bottleneck is happening from loading the data into the controls.
It is possible to have multiple UI threads in a single WinForms application. Each UI thread must call Application.Run() and you'd need to mark the entry point to each with [STAThread] just like you do in the Main function.
I have successfully done this and it's a reasonable approach when faced with an existing codebase that's doing too much work on its UI thread. But... I would say this is a symptom of a design that could be improved in other ways. If you're doing too much work on your UI thread think about ways to get that work done on other threads. In my apps I've tried to get all non-trivial work done on non-UI threads. It can be done, but it's not always the fastest way to deliver software.
If doing no other work, a single UI thread is ample to draw 8 screens full of numbers and charts, and update them more frequently than a human can keep up. I know this to be the case :-)
This is technically doable, more flexible in WPF than in WinForms (in my experience), but not recommended in either. Windows client apps tend to run with a single thread responsible for drawing the UI; typically background threads are used for background processing of data access or business logic. Additionally, you'd have to be doing a lot of work in the UI for rendering performance to actually be an issue - this sounds like unnecessary work to me.
However, the basic style in WinForms would be something like this:
var t = new Thread(() =>
{
var f = new Form1();
Application.Run(f);
})
t.Start();
Things you need to be aware of:
you will always have to Invoke calls between forms to make sure they're on the right thread.
if anything in your business layer has thread affinity, you'll need one instance per form that uses it.
application shutdown typically happens in response to the main thread's forms closing. You may need to handle your shutdown manually, though with the code above you have two message loops running and either will keep the app alive when the other's form closes.
Always do data crunching, receiving from I/O, parsing and whatnot on a separate thread or several threads if you need/want.
Then if you're loading a lot of data to UI controls, make sure you don't synchronize with the UI thread too often, like if you invoke every single item from an input stream separately and there are thousands of these per second - WinForms will grind to a halt.
Queue visual data changes in your background thread(s) and batch them to the UI thread with a minimum interval so as to not do this too often - the thread sync is expensive. AddRange is your friend.

C# cross-thread operation not valid, 2 controls and 2 separate threads

Here's a simplified example of what I'm trying to do:
I have 2 controls MyControl c and Panel p. p is created in the main GUI thread as normal, but I want c to be created in a background thread, because it takes awhile and I don't want to freeze the GUI. How can I add c to p.Controls? If I do it in this.Invoke it throws an exception for c, and if I do it from the background thread it throws an exception for p.
Or is it that I really shouldn't be creating GUI elements outside of the main GUI thread?
Or is it that I really shouldn't be creating GUI elements outside of the main GUI thread?
Yes, this is basically the problem. Most controls have thread affinity, and must be created within the user interface thread.
Typically, the way to handle this is to move the "work" that is causing the control creation to be slow onto a background thread, but still create the control on the UI thread. You'd then use Control.Invoke or Control.BeginInvoke to update the information in the UI once the slow work was completed.
For example, if you're loading a set of data from some external source, you can create the control, and start a background thread to load the data. Once the data is loaded, you can then update the control to reflect it. This will cause it to stay responsive the entire time.
It may be that your control does not take a long time to create; rather it takes a long time to get its data. In that case, consider creating a control that can display it UI while it is being populated. Then you can create the control in your main thread, populate it in a background thread, and give your users a better experience.
Use background thread to do what it has to do, and then signal somehow (bool _backgroundCompleted as a trivial example) that c is ready to be created.
Create c from Timer that will fire periodically and do nothing until _backgroundCompleted is set, then create c, then kill the timer.
It might be 'ugly', but it will work and will remain simple.
Forms.Timer, if you are asking ;)
And yeah, NEVER ever mess with multiple threads on the same form. You can have several forms on several threads, but to do that, you have to first RUN a new thread, then create a form ON it. It will have its own message loop, and will do fine.

UI freezing problem in c# 2.0

Sometimes I saw that when I call a method from my form to do something that my UI freezes. How to solve this problem? If I call that method in separate thread then problem will be solved?
If I call method in separate thread like the code below
new System.Threading.Thread(delegate()
{
HeavyMethod();
}).Start();
does this solve my problem or is there any better solution?
Call the method on a Background Worker would be the best solution.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Doing that you can control when things get updated (using the Report Progress Feature) and allow you to cancel the work.
Also, make sure that whatever resources you manipulate in the backgroundWorker1.RunWorkerAsync(); are properly shared. You can get into what is called "Race Conditions" which causes your output to be non-determanistic (e.g. you won't get the same results every time you run the method)
For a good walk through on Multithreading and shared resources, see this link:
http://www.c-sharpcorner.com/uploadfile/mgold/multithreadingintro10062005000439am/multithreadingintro.aspx?articleid=920ecafc-e83b-4a9c-a64d-0b39ad885705
If you are calling your method in response to an event, then by default the method will be running on the GUI thread (the thread that the runtime uses to handle all user events). If that method is huge and/or heavy, then it will "freeze" the UI as you describe.
Making it run on a separate thread is a viable solution for many of these cases.
There are cases, however, when you'll actually want the UI to "block" (for example, if you are updating a lot of controls, you don't want the user to mess with them in the meanwhile). For such cases, the sanest approach is to pop up a modal "wait" dialog.
Since it is C# 2.0, I suppose it is WinForms. Don't hold up the UI thread with CPU-bound code.
You can spawn a new thread to run your CPU-bound code, but you have to be careful not to access WinForms controls, especially not to update control properties. Many WinForms controls can only be accessed/updated from the UI thread. Check the InvokeRequired field to see if you need to marshal (i.e. use Invoke) the call from another thread back to the UI thread.
Also consider using the ThreadPool instead of creating a new thread.
That is correct, If you move the heavy processing off of the UI Thread then it should free up the UI to redraw. For what you want to do your implementation should work just fine. Although ThreadPooling or BackgroundWorker would be the suggested implementations (http://msdn.microsoft.com/en-us/library/system.threading.threadpool(v=VS.80).aspx), (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx).

Categories