Putting a Form on a new thread

  • Thread starter Thread starter Brandon Owensby
  • Start date Start date
B

Brandon Owensby

If I try to start my form on a new thread it doesn't stay up. You see it
appear on the screen but then it disappears after just a second or so. How
do you go about putting a form on another thread without that happening?
Any help is greatly appreciated.

Thanks,
Brandon
 
Could you post the code you use to create the thread and the code of the
function which creates the form?
 
I will not do the actuall code but a small representation

I know this may look slightly weird but yes I have to have the 2nd class and
yes the second class will fire its code from the constructor. All I need is
some guidence as to how its suppose to be done even if it doesn't fit this
mode and I will make it fit my mode somehow.

Thanks,
Brandon



public class Form
{
public Form()
{
--code to setup window
this.Show()
--more code to setup window
}
}

public class FormStarter
{
FormStarter()
{
new System.Threading.Thread(new
System.Threading.ThreadStart(this.StartForm)).Start();
}

public void StartForm()
{
new Form();
}
}
 
The problem is that after StartForm finishes executing, the thread
dies. Any thread will die after it runs out of code to execute.

The real question here is, why are you trying to have a seperate thread
own the Form? UI resources are really meant to be owned by the main
thread. It really makes more sense to have a seperate thread do
something with or to the Form.
 
Brandon Owensby said:
If I try to start my form on a new thread it doesn't stay up. You see it
appear on the screen but then it disappears after just a second or so.
How do you go about putting a form on another thread without that
happening?

Create all forms in the main UI thread and use
'Control.Invoke'/'Control.BeginInvoke' to access them from a worker thread:

Multithreading in Windows Forms applications
<URL:http://dotnet.mvps.org/dotnet/faqs/?id=multithreading&lang=en>
 
Hi Adam,

Your statement
UI resources are really meant to be owned by the main
thread. It really makes more sense to have a seperate thread do
something with or to the Form.

Is not completely correct. You can have as many as you want UI threads. Each
UI thread provides separate UI :) Even though it is not common it is not
wrong. Windows Explorer for example... Each eplorer is a new UI thread in
the same process. .NET application domains - from OS prespective this noting
more than one process with more than one UI threads.

So here the correction of the code:

1. remove this lines from the form's constructor

2. Restore the code that the form should have; namely a call to
InitializeComponent method. It has to be there if you use VS.NET designer.

3. The thread proc should be:

public void StartForm()
Application.Run method is the one that makes a thread a UI thread. It runs
the windows messages loop (pump). While this loop pumps messages the form
will be alive.


HTH
Stoitcho Goutsev (100) [C# MVP]

"
 
Hi Herfried!

Is that the ultimate rule?

I want in my apps plugins. And the plugins runs long. And they need an UI.
And i need results from the plugins ?

wolfgang
 
There is one thing that you (Jon) and Herfried are not thinking about. The
reason that we want this window on another thread wich Stoitcho explained
how to do is because of another window we have. We have an application that
has a window used for editing entitys in our database. When that screen
comes up we don't want them to go back to the application and be able to do
anything until the finish with that screen. That has worked great for us so
far. Now, however, we have another screen I'm writing that is a utility
that can and should be used whenever the need. This utility(a scheduler to
be exact) is loaded off of the main application but is not to be hindered by
anything on the application. The editor window is a dialog window which is
why it would hinder the scheduler. This being the case your ideas do not
fit my scenario. Anyways it sounds like the Application.Run is the way to
go.

Thanks,
Brandon
 
Brandon Owensby said:
There is one thing that you (Jon) and Herfried are not thinking about. The
reason that we want this window on another thread wich Stoitcho explained
how to do is because of another window we have. We have an application that
has a window used for editing entitys in our database. When that screen
comes up we don't want them to go back to the application and be able to do
anything until the finish with that screen. That has worked great for us so
far. Now, however, we have another screen I'm writing that is a utility
that can and should be used whenever the need. This utility(a scheduler to
be exact) is loaded off of the main application but is not to be hindered by
anything on the application. The editor window is a dialog window which is
why it would hinder the scheduler. This being the case your ideas do not
fit my scenario. Anyways it sounds like the Application.Run is the way to
go.

No, you can just bring up a new Form on the main UI thread (using Show
() or setting Visible to true). Nothing wrong with that. Just avoid
doing a lot of work on the UI thread. Application.Run is basically
there to set up a message pump on a thread - you don't need to do that
if you're already running one (on the UI thread).
 
But as I explained in my prior message we have another screen that comes up
as a dialog. If you bring that screen up you cannot use the other one.
This is not an assumption. This is something I have experienced. I've had
this happen with several of our windows. I will go load up this dialog
window and then if I decided to go use another one of my windows forgetting
I had this one pulled up it won't let me use it. I then have to close out
of the dialog window. It just happens to be that for the Scheduler we want
them to be able to bring up the dialog screen and still be able to come back
to the scheduler and use it without closing out of the dialog screen. This
is the first screen we've wanted the user to have that option. If what you
are saying is correct then there is something I'm doing wrong because I'm
doing now exactly what you are talking about. If it had worked them I would
be ok with it but it doesn't so I wrote my message. So either there is
something I have to do differently than new Form() and Form.Show() or I
need to use the Application.Run().

Which is it? I'm confused?

Brandon
 
[Same reply as posted by email. Please don't email me a copy of
messages you'll post on the group - it ends up causing confusion.]

Brandon Owensby said:
But as I explained in my prior message we have another screen that comes up
as a dialog. If you bring that screen up you cannot use the other one.
This is not an assumption. This is something I have experienced. I've had
this happen with several of our windows.

I suspect you use ShowDialog then. If that's not it, perhaps you could
provide a short but complete program which shows what you're doing with
a sample form.

Here's a very simple app which shows it's possible:

using System;
using System.Windows.Forms;
using System.Drawing;

class Test : Form
{
Test()
{
Size = new Size (500, 300);
Button b = new Button();
b.Text = "Click me";
b.Click += new EventHandler (ButtonClick);
b.Location = new Point (50, 50);
Controls.Add(b);
}

void ButtonClick (object sender, EventArgs e)
{
new Test().Show();
}

[STAThread]
static void Main()
{
Test t = new Test();
Application.Run(t);
}
}

If you compile and run that, each time you click on a button it'll
create a new copy of itself. However, you can click on the button on
any of the forms, either the newly created one or another one. In other
words, they're all running at the same time.
 
I just wanna make sure I understand your message correctly. First off I
neversaid the initialize component was gone. I guess honestly it isn't in
the constructor I was using as an example (not that that could of been
derived one way or another from my message) it was in the second one. When
I have a form that needs paramaters then I create another constructor with
this paramaters but have it also call the other constructor.

public Form(parameters) : this.Form()
{
code
}

This gives me the ability to write code to setup the window without having
to duplicate the call to initiliaze component. It also gives me a common
place to write code for all constructors. I can see why I have to change
that. It worked before Application.Run so why wouldn't it work with it. I
just wanna understand it as much as possible. If there is something I'm
missing please let me know.

Thanks,
Brandon
 
Jon,

The example you have written does not work if the forms are displayed
with ShowDialog(). I think ShowDialog() is also what Brandon is using
to pop up the "edit entity form".

I'm having the exact same problems with my application at the moment. I
have Form, FormB and FormC. FormA and FormB are both from FormC with
Show(). There's a button on FormB which opens FormX using ShowDialog().
I need to stop users from going to FormA when FormX is there, but FormB
must still be accessible. Just like Brandon described, both FormA and
FormB are inaccessible to the user while FormX is up.

I've created a skeletal project to represent the forms with just the
bare essentials. The problem seems to be solved if I do the following:

// in FormC
Thread thread = new Thread(new ThreadStart(OpenFormMethod));
thread.Start();

// in OpenFormMethod, or whatever method the thread calls
Thread t = Thread.CurrentThread;
Application.Run(new FormB());
Application.ExitThread(); // this is really just for me. you might not
want to call this here.

Now the modal dialog FormX does not block FormB.


HTH,
Cryo
 
Brandon,

You can construct your code as you please. The key point is that you need to
show the form with Application.Run(). This is what brings the form to life.
 
Back
Top