Like many others, I need to open WinForms on other threads. After reading a lot of different articles, I see that it is not possible but my question is will it be possible at a time or is there a way to achieve the following goal?
I'm creating an application with a lot of tool windows that are long to initialize (because of many controls or other things that cannot be put on worker threads) and these tools windows are not needed immediately when the main application starts but I still want to show them when they'll be ready to be used.
Is this possible to achieve in some way without needing a feature, WinForms on other threads, that seams to be currently impossible now?
thanks in advance
EDIT
All of you, thanks for the good articles and hints but it was my error to not provide any more details about one of my re开发者_开发知识库al nead. I'm currently using a third party control that enables me to open WinForms in an MDI container as tabbed windows (i'm using Telerik.WinControls.UI.Docking.RadDock). For this, the Main UI thread, the one that host the RadDock, needs to be informed of newly added Winforms to be able to add them to is "tabbed" window list. This is one of the thing that I do not see how it can be done because this will involve that one of my tool window, created on another thread, can be marshalled and be used on the main thread.
Its not that you need to show your WinForms on other threads, rather, you need to make the work inside those forms asynchronous and implement proper thread-safe synchronization. I have two blog articles that apply to just this.
- Using ISynchronizeInvoke to update your UI safely from another thread
- Writing thread-safe event handlers with the Task Parallel Library (includes source code)
Both are for Windows Forms, and there are tons of articles you can find on making your WinForms asynchronous.
A for instance.
ToolWindowForm form = new ToolWindowForm()) {
form.Show();
// other code
Let's say you have this somewhere in your code where you need this tool window to display, but it takes such a long time to load it blocks the rest of your code from execution. Well, showing the form on another thread could be one way to accomplish this, and is very much so possible. What can make this exceedingly complex though is that if you are communicating between forms and need access to controls, you are going to run into CrossThreadViolations and IllegalCrossThreadCalls. Its easier and safer just to make the work behind each form asynchronous.
Edit If its a must you can add private members to store instances to the forms, ie.
private Form m_MyToolForm = new Form();
private Form m_MyToolForm2 = new Form();
Then somewhere in code.
public void ShowToolForm() {
Thread thread = new Thread(new ThreadStart(ShowToolFormAsync));
thread.IsBackground = true;
thread.Start();
}
private void ShowToolFormAsync() {
m_MyToolForm.ShowDialog(); // Blocks on this thread
}
You can also use the Task Parallel Library if you are on .NET 4.
Task.Factory.StartNew(() => m_MyToolForm.ShowDialog());
I dont seem how this would not be possible. The only big problem with creating forms and updating form controls over different threads, is that you will need a thread-safe callback otherwise you will get errors that only the parent thread who created the form is able to update a gui.
More information about this thread-safe callback and the InvokeRequired stuff which is required with this cross-threading is found at : http://msdn.microsoft.com/en-us/library/ms171728%28v=vs.80%29.aspx
精彩评论