C# Threads  
Author Message
Neil Ault





PostPosted: Visual C# General, C# Threads Top

Hi,

I have a problem with thread and i'm hoping someone can help me.

I start a thread with the following code...

Thread m_NewThread = new Thread(new ThreadStart(DoWork));
m_NewThread.Start();

The threaad starts find and executes the code within DoWork, for example:

private void DoWork()
{

...

//Finished work so show thread finished
ThreadFinished();

}

Again it executes the code within ThreadFinished, for example:

private void ThreadFinished()
{

....

//Thread has finished so show finish form and close
frmFinished f = new frmFinished();
f.Show();
this.Close();

}

Now this is where it goes wrong. Stepping through this code it show's the finished form as you can see it in the taskbar but as soon as the close statement is executed it closes not only the current form but the new finished form as well.

Any ideas

Thanks in anticipation...


Neil



Visual C#12  
 
 
boban.s





PostPosted: Visual C# General, C# Threads Top

If you close the parent form, the child form (in this case frmFinished) will be closed also. You must find other way of opening finished form or keeping it opened. That can be for example if you don't close the parent form, but just hide it, and when you close the Finished form to close the parent form also (for this you need to hook finished form closed event). Or you can call finished form from main app form if you send the thread finished event to the main app form where it will be handled and will open finished form.

 
 
Mark Dawson





PostPosted: Visual C# General, C# Threads Top

Hi,

can you post the code you want to try to convert, otherwise it is impossible to see what you want to do. I would suggest that first you read this article http://www.yoda.arachsys.com/csharp/threads/ to hepl you understand threads in C# then if you have any specific question post your code.

Mark.



 
 
Keith Rome





PostPosted: Visual C# General, C# Threads Top

First of all, your ThreadFinished() method is being called from DoWork(), which is running on a secondary thread - this means that all of the code you have in ThreadFinished() should *not* be touching any UI controls. You should alter your code to use a BackgroundWorker instead of a basic Thread object:

Thread m_NewThread = new Thread(new ThreadStart(DoWork));

m_NewThread.Start();

BackgroundWorker m_Worker = new BackgroundWorker();

m_Worker.DoWork += new DoWorkEventHandler(DoWork);

m_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ThreadFinished);

m_Worker.RunWorkerAsync();

void DoWork(object sender, DoWorkEventArgs e)

{

/* Do your processing here - but don't touch any objects that

* inherit from Control (DoWork executes on background thread) */

}

void ThreadFinished(object sender, RunWorkerCompletedEventArgs e)

{

/* Safe to mess with Controls now (RunWorkerCompleted executes on main thread) */

//Thread has finished so show finish form and close

frmFinished f = new frmFinished();

f.Show();

this.Close();

}

However, that is probably only part of your problem. I am betting that your code sample belongs to the main form of the application - the one passed to Application.Run() in program.cs. If that is true, then calling this.Close() will cause your main application form to close, which effectively terminates your application.

HTH



 
 
Neil Ault





PostPosted: Visual C# General, C# Threads Top

Unfortunately at the moment I am having to use the .NET Framwork v1.1 (until we upgrade to Visual Studio 2005 sometime next year) and it doesn't support BackgroundWorker, so I'm going to be unable to do things this way.

The code sample I gave you, thankfully, does not exist in the main form of the application. Basically I am developing a small zip utility; the main form runs in the systray and when the user selects to create a new zip a new create form is shown that allows them to set certain options. The zip process is then started off in a thread i.e. the DoWork() (did it this way so I could update progressbars and such like easily). When the thread was finished what I wanted to happen was a new form (the view zip form) was shown with the newly created zip showing and the create form to close. When in reality what happens is that the view zip form shows and then closes when the create zip form closes leaving the main app form still running.

I tried one other suggestion that was to put the ZipFinished() method into the main app form and call that from the thread but the same thing happens. And finally just to get around things for now I took another suggestion (which I hated doing) which hides the create zip form, shows the view zip form and then when the view zip form is closed it goes back and closes the relevant create zip form.

So any other suggestion would be cool, or I guess I wait until we upgrade to v2.0.

Neil


 
 
ahmedilyas





PostPosted: Visual C# General, C# Threads Top

I would suggest raising an event in the main thread from your second thread to notify that its finished so the event will show the secondform from your main UI thread

 
 
Keith Rome





PostPosted: Visual C# General, C# Threads Top

If you are unable to use framework 2.0, then you need to at least marshall the call to ThreadFinished() into the main UI thread so that your interactions with the GUI are safe. You can use Control.InvokeRequired and Control.Invoke() to accomplish this. And actually, BackgroundWorker does this for you, just in a cleaner way.

private void Form1_Load(object sender, EventArgs e)

{

Thread m_NewThread = new Thread(new ThreadStart(DoWork));

m_NewThread.IsBackground = true; // this prevents the extra thread from blocking an application shutdown

m_NewThread.Start();

}

void DoWork()

{

/* Do your processing here - but don't touch any objects that

* inherit from Control (DoWork executes on background thread) */

Thread.Sleep(5000); // simulating some work

ThreadFinished();

}

delegate void ThreadFinishedEvent();

void ThreadFinished()

{

// Marshall back into the main thread if needed

if (this.InvokeRequired)

this.Invoke(new ThreadFinishedEvent(ThreadFinished));

else

{

/* Safe to mess with Controls now */

//Thread has finished so show finish form and close

//frmFinished f = new frmFinished();

//f.Show();

//this.Close();

MessageBox.Show("Done"); // doing stuff with GUI controls

}

}

HTH



 
 
Neil Ault





PostPosted: Visual C# General, C# Threads Top

Works a treat!

Thanks...

Neil