Launching copies of a WinForm app from within itself

M

michael sorens

I have a WinForm application that, depending on user actions, may spin for a
while doing extensive calculations, showing a progress bar in the meantime.
I would like to be able to launch a second complete copy of the main form so
the user may start a second lengthy calculation if desired.
I have a menu item to "Launch New Workspace" but I am having difficulty
implementing this. I detail my experiments below; any suggestions on the
proper way to do this would be appreciated.
[Environment: WinXP, VS2008, .NET 2.0]

===========
Attempt #1:
===========
This creates a new workspace that works, except that when the first
workspace is tied up doing calculations, this one is locked up as well since
it is in the same thread.

private void LaunchNewWorkspace()
{
new MainForm().Show();
}


===========
Attempt #2:
===========
This attempts to create a new thread.

private void LaunchNewWorkspace()
{
Thread newThread = new Thread(new ThreadStart(NewWorkspaceThreadStart));
newThread.Start();
}
private void NewWorkspaceThreadStart()
{
new MainForm().Show();
}

During initialization of the new new workspace I get this error:
System.Threading.ThreadStateException was unhandled: Current thread must be
set to single thread apartment (STA) mode before OLE calls can be made.
Ensure that your Main function has STAThreadAttribute marked on it.

The above error occurs on this statement:
this.myComboBox.AutoCompleteMode =
System.Windows.Forms.AutoCompleteMode.SuggestAppend;


===========
Attempt #3:
===========
Variation of previous attempt.

private void LaunchNewWorkspace()
{
Thread newThread = new Thread(new ThreadStart(NewWorkspaceThreadStart));
newThread.Start();
}
[STAThread]
private void NewWorkspaceThreadStart()
{
Application.Run(new MainForm());
}

This resulted in the same error at the same location. Some cursory reading
about the STAThread attribute seemed to indicate it is something that should
not be needed; I am uncertain how to proceed with this.


===========
Attempt #4:
===========
Further research found this pattern, which I am guessing is an older
approach to threading.

private void LaunchNewWorkspace()
{
MainForm workerObject = new MainForm();
Thread newThread = new Thread(workerObject.NewWorkspaceThreadStart);
newThread.Start();
}
private void NewWorkspaceThreadStart()
{
Show();
}
System.InvalidOperationException was unhandled: Cross-thread operation not
valid: Control 'statusStrip' accessed from a thread other than the thread it
was created on.


===========
Attempt #5:
===========
Double-click on my application icon on my desktop:)
This works, creating a completely independent process, but is not integrated
into the application as a menu choice as I would like.
 
M

Micha³ Piaskowski

===========
Attempt #5:
===========
Double-click on my application icon on my desktop:)
This works, creating a completely independent process, but is not integrated
into the application as a menu choice as I would like.

===========
Attempt #5:
===========
Double-click on my application icon on my desktop:)
This works, creating a completely independent process, but is not integrated
into the application as a menu choice as I would like.

This code will do exactly the same from you application (create
another instance of your program)

<code>
using System.Diagnostics;

ProcessStartInfo psi = new
ProcessStartInfo(Application.ExecutablePath);
System.Diagnostics.Process.Start(psi);

</code>

Although I'd personally suggest a different approach.
Instead of creating a new window, try to run your calculations on a
separate thread while allowing user to continue using the rest of
application.

Micha³
 
P

parez

I have a WinForm application that, depending on user actions, may spin for a
while doing extensive calculations, showing a progress bar in the meantime.
I would like to be able to launch a second complete copy of the main form so
the user may start a second lengthy calculation if desired.
I have a menu item to "Launch New Workspace" but I am having difficulty
implementing this. I detail my experiments below; any suggestions on the
proper way to do this would be appreciated.
[Environment: WinXP, VS2008, .NET 2.0]

===========
Attempt #1:
===========
This creates a new workspace that works, except that when the first
workspace is tied up doing calculations, this one is locked up as well since
it is in the same thread.

private void LaunchNewWorkspace()
{
new MainForm().Show();

}

===========
Attempt #2:
===========
This attempts to create a new thread.

private void LaunchNewWorkspace()
{
Thread newThread = new Thread(new ThreadStart(NewWorkspaceThreadStart));
newThread.Start();}

private void NewWorkspaceThreadStart()
{
new MainForm().Show();

}

During initialization of the new new workspace I get this error:
System.Threading.ThreadStateException was unhandled: Current thread must be
set to single thread apartment (STA) mode before OLE calls can be made.
Ensure that your Main function has STAThreadAttribute marked on it.

The above error occurs on this statement:
this.myComboBox.AutoCompleteMode =
System.Windows.Forms.AutoCompleteMode.SuggestAppend;

===========
Attempt #3:
===========
Variation of previous attempt.

private void LaunchNewWorkspace()
{
Thread newThread = new Thread(new ThreadStart(NewWorkspaceThreadStart));
newThread.Start();}

[STAThread]
private void NewWorkspaceThreadStart()
{
Application.Run(new MainForm());

}

This resulted in the same error at the same location. Some cursory reading
about the STAThread attribute seemed to indicate it is something that should
not be needed; I am uncertain how to proceed with this.

===========
Attempt #4:
===========
Further research found this pattern, which I am guessing is an older
approach to threading.

private void LaunchNewWorkspace()
{
MainForm workerObject = new MainForm();
Thread newThread = new Thread(workerObject.NewWorkspaceThreadStart);
newThread.Start();}

private void NewWorkspaceThreadStart()
{
Show();}

System.InvalidOperationException was unhandled: Cross-thread operation not
valid: Control 'statusStrip' accessed from a thread other than the thread it
was created on.

===========
Attempt #5:
===========
Double-click on my application icon on my desktop:)
This works, creating a completely independent process, but is not integrated
into the application as a menu choice as I would like.

Instead of MainForm, you can use another form as the starting form.
From that starting form, you could open multiple instances of the old
main form.
 
L

Linda Liu[MSFT]

Thanks Piaskal for your reply!

Hi Michael,
I would like to be able to launch a second complete copy of the main form
so the user may start a second lengthy calculation if desired.

In my opinion, you may not need to start a second instance of the
application to start a second lengthy calculation. You can use a
BackgroundWorker component to do the time-consuming work in a separate
thread.

For more information on how to use the BackgroundWorker component, see the
following MSDN document:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundwork
er.aspx

The solution that Piaskal suggested works perfectly. If you really want to
start a second instance of the application from within the application
itself, you can adopt the solution that Piaskal provided.

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

michael sorens

I agree that a BackgroundWorker would be appropriate in certain
circumstances; in my particular case it is not the best choice due to other
factors I did not mention (as I wanted to keep the post as short as I could).

So: I am aware of the ProcessStartInfo class, but I would have thought that
I could achieve an equivalent result with threads; I infer from your
responses that this is not the case (or at least not simple). Just for
academic curiosity, is there a short answer as to why?

My real follow-up questions, though, are these:
I tried the approach with ProcessStartInfo and it launched fine, but I
notice that it did *not* read the user.config file that the first instance of
the application used. (Not sure if it read *any* user.config file). Also,
could I somehow attach Visual Studio to the second process for debugging?
 
M

michael sorens

Sorry for jumping the gun on my prior post--I found the answers to my two
main questions:
(1) The user.config was different because the first instance was running
app.vshost.exe while the second instance ran app.exe.
(2) I found how to attach and debug existing processes in VS.

That leaves only the minor academic question as to why my attempt with
threads was unsuccessful...
 
S

Stephany Young

There is nothing academic about why your attempts with threads didn't work.

It's simply that they were, at least, inappropriate.

As you figured out for yourself, Attempt #2 failed because you didn't have
NewWorkspaceThreadStart marked as an STA thread.

Attempt #3 failed because, although you marked NewWorkspaceThreadStart as an
STA thread, you also did attempted to start a new main message pump:
Application.Run(new MainForm()) instead of new MainForm().Show().

As for Attempt #4, workerObject (new MainForm()) was created on the main UI
thread and then you attempted to 'show' it from another thread (newThread).


michael sorens said:
Sorry for jumping the gun on my prior post--I found the answers to my two
main questions:
(1) The user.config was different because the first instance was running
app.vshost.exe while the second instance ran app.exe.
(2) I found how to attach and debug existing processes in VS.

That leaves only the minor academic question as to why my attempt with
threads was unsuccessful...




===========
Attempt #4:
===========
Further research found this pattern, which I am guessing is an older
approach to threading.

private void LaunchNewWorkspace()
{
MainForm workerObject = new MainForm();
Thread newThread = new Thread(workerObject.NewWorkspaceThreadStart);
newThread.Start();
}
private void NewWorkspaceThreadStart()
{
Show();
}
System.InvalidOperationException was unhandled: Cross-thread operation not
valid: Control 'statusStrip' accessed from a thread other than the thread it
was created on.


===========
Attempt #5:
===========
Double-click on my application icon on my desktop:)
This works, creating a completely independent process, but is not integrated
into the application as a menu choice as I would like.
 
L

Linda Liu[MSFT]

Hi Michael,

Thank you for your reply!
That leaves only the minor academic question as to why my attempt with
threads was unsuccessful...

The error in your solution in the Attempt #4 is apparent. WinForm
programming model doesn't allow cross-thread operation, i.e. a control can
be accessed only by the thread in which it is created.

The solution in the Attempt #3 makes more sense than that in the Attempt
#2, because it sets up a new message loop for the new instance of MainForm.
Note that in both solutions in Attempt #2 and #3 the old and new instances
of MainForm runs in a same process. You can see this in the Processes tab
in the Windows Task Manager.

Unfortunately, OLE calls requests STA mode for the application, so the
solution in the Attempt #3 doesn't work if you have OLE calls in the
application.

Thus, the robustest solution is to start a new process for the application
using the Process class. And in this case, there will be really two
processes running on the machine.

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top