So I'm still fairly new to C#. Im learning about threads.
So far I would like to know how to check if a thread has ended. I know that i can put a bool at the end of the method the thread uses and use that to determine if the thread ends.. but i dont want to do that, mainly because i want to learn the right way
so far I have this.
Thread testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
I read about the thread.join(); class. To my understanding, that class only prevents any code after that from executing.. Please help
Well there are different ways that give different results
1 ) Wait until the work has finished. This is exactly what you've got with your code already. You'll start a thread and then wait for that thread to finish before continuing execution.
thread.Start();
thread.Join();
2) thread.ThreadState will tell you whether or not the thread has finished. In a basic scenario you could do the following. This would allow you to check the current thread state at any point in your code where you've got access to the state.
if(thread.ThreadState != ThreadState.Running){
// Thread has stopped
}
3) Using an event. A lot of Async examples will start some work and then trigger an event once the work has been completed. In this way you can sit watching for an event and respond once the work has completed. A usage example may look like the WebClient class
WebClient client = new WebClient();
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
Thread.Join() Blocks the thread you call it on until the thread you have called Join() on returns. Extending the example you have above:
Thread testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
//Do more stuff here. This stuff will not start until testThreadd has completed its work.
you can do this
public partial class MainWindow : Window
{
Thread testThreadd;
public MainWindow()
{
InitializeComponent();
testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
}
public void Testmethod()
{
// begining your treatement
// Ending your treatement
this.testThreadd.Abort();
}
}
Thread.Join method pauses current thread execution until second thread completes. It serves for thread synchronization and it's well enough indicator.
Otherwise, you should use Thread.IsAlive property to check if thread is running while not interrupting current thread. This property covers any state between Thread.Start and the end of the thread.
Related
I have a WinForms application on .NET 3.5. In this form, the user triggers an operation which is executed in another thread (a BackgroundWorker to be precise) so as to not block the UI thread. I'm in MVP, so all this is being done by a presenter which interacts with an interface to the view (implemented by the Windows Form). So far so good.
I would like to introduce functionality whereby a timeout period is introduced for the background operation to complete before cancelling it. Sounds simple enough. But the background operation calls a single function on a third-party component which may never return, so the cancellation capabilities of the BackgroundWorker are of no use to me here. Also, the BackgroundWorker.RunWorkerCompleted allowed me to get back on the UI thread, so I need to wait for the timeout or success and be able to get back to my calling thread (namely the UI thread).
I tried this using a plain old Thread (which does support Abort()) and a Timer running on a second thread, but can't seem to get it to work quite right since Join() is blocking my UI thread despite the description stating that it will block "while continuing to perform standard COM and SendMessage pumping". Admittedly I assumed this implied that it would continue to process Windows Messages, which was not the case.
int timeoutInMsec = 10000;
Thread connectThread = new Thread(Connect);
Thread timerThread = new Thread(() =>
{
var timer = new System.Windows.Forms.Timer() { Interval = timeoutInMsec };
timer.Tick += (_s, _e) =>
{
timer.Stop();
if (connectThread.ThreadState == ThreadState.Running)
connectThread.Abort();
};
};
connectThread.Start();
timerThread.Start();
timerThread.Join();
connectThread.Join();
Based on this question, I tried removing the second timer thread and adding a ManualResetEvent and calling Set() when the timer ticked, or when the Connect method did indeed complete. Here, instead of Join I used WaitOne, but unfortunately this also blocks my UI thread. I also found this other question, which a CancellationTokenSource which unfortunately is not available in .NET 3.5.
So, how can I spin my worker up and be able to terminate it after a given amount of time in .NET 3.5, while at the same time be able to get back to the thread where I spun up the worker thread to execute a sort of OnCompleted handler?
Many thanks in advance!
PS: I don't have a lot of experience in multi-threaded programming in .NET, so I'm sorry if this is trivial.
If I understood your question correctly, the following algorithm should solve your problem:
As before, create a BackgroundWorker to do your background work.
In BackgroundWorker_DoWork,
create a new thread (let's call it the "third-party thread") to call your third-party library, and then
wait for the third-party thread to finish or the timeout to elapse. (*)
That way, your UI won't block, since only the Backgroundworker thread is waiting, not the main thread.
Now about the interesting part: How do you wait for the third-party thread to finish (the step marked with (*))?
My suggestion would be to simply use "loop waiting with sleep", i.e. (pseudo-code, you can use the Stopwatch class for the timeout):
do until (third-party thread has finished or x seconds have elapsed):
Thread.Sleep for 100ms
if third-party thread has not finished:
Abort it // we don't have another choice
else
Process the result
It's not best practice, but it's simple, it gets the job done and you can always replace it with fancy cross-thread-syncronization stuff (which is non-trivial to get right) once you got it all working.
It's useless to create a Forms.Timer on a non-gui thread. Don't create it on a separate thread. Why are you Joining the threads? The usage of Join is to block the current thread until the other thread is finished.
This is untested pseudo code, this is for example purpose.
public class Form1: Form1
{
private int timeoutInMsec = 10000;
private System.Windows.Forms.Timer _timer;
private Thread _connectThread;
public Form1()
{
_connectThread = new Thread(Connect);
_connectThread.Start();
_timer = new System.Windows.Forms.Timer() { Interval = timeoutInMsec };
_timer.Tick += (_s, _e) =>
{
_timer.Stop();
if (_connectThread.ThreadState == ThreadState.Running)
_connectThread.Abort();
};
};
}
private void Connected()
{
}
private void Aborted()
{
}
private void Connect()
{
try
{
DoConnect3rdPartyStuff();
this.Invoke(Connected);
}
catch(ThreadAbortException)
{
// aborted
this.Invoke(Aborted);
}
}
}
So I'm still fairly new to C#.
So far I would like to know how to check if a thread has ended. I know that i can put a bool at the end of the method the thread uses and use that to determine if the thread ends.. but i dont want to do that, mainly because i want to learn the right way
so far I have this.
Thread testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
I read about the thread.join(); class. To my understanding, that class only prevents any code after that from executing.. Please help.
thanks
Well there are different ways that give different results
1 ) Wait until the work has finished. This is exactly what you've got with your code already. You'll start a thread and then wait for that thread to finish before continuing execution.
thread.Start();
thread.Join();
2) thread.ThreadState will tell you whether or not the thread has finished. In a basic scenario you could do the following. This would allow you to check the current thread state at any point in your code where you've got access to the state.
if(thread.ThreadState != ThreadState.Running){
// Thread has stopped
}
3) Using an event. A lot of Async examples will start some work and then trigger an event once the work has been completed. In this way you can sit watching for an event and respond once the work has completed. A usage example may look like the WebClient class
WebClient client = new WebClient();
client.DownloadFileCompleted += new
AsyncCompletedEventHandler(client_DownloadFileCompleted);
You can check for Thread.IsAlive property.
What you tried is a right way to wait for a thread to be done. But:
Thread.Join() is a function of Thread class.
Calling Join() function of a thread instance (in your sample testThreadd) will make the current thread to wait until testThreadd finishes it's job. Current thread is the thread which is calling testThreadd.Join()
In addition to the supplied answers, these days, the most used method would be by using Tasks. Besides having all the Wait and IsCompleted possibilities, these have the added advantage of having a ContinueWith method
start a task
var task = Task.Run((Action)TestMethod);
check completed
if (task.IsCompleted) { }
wait for task to finish (same as thread.sleep)
task.Wait();
setting a continuewith (additional task to be started after the task finishes)
var task = new Task((Action)TestMethod);
task.ContinueWith(t => MessageBox.Show("Finished"));
task.Start();
and combined, waiting for the continued task to finish (which automatically means, the first task is finished)
var task = new Task((Action)TestMethod);
var continuedtask = task.ContinueWith(t => MessageBox.Show("Finished"));
task.Start();
continuedtask.Wait();
You could use a BackgroundWorker instead of manually starting a new thread. It raises the RunWorkerCompleted event if its work is done (or if an exception occurs).
I have started a special course in multithreading but I have some fundamental issues I want to clear up. say I have a thread
Thread t1 = new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
IsCancel = false;
this.workProj.DoWorkWithRefSync(ref IsCancel);
});
t1.Start();
Followed by
while(t1.IsAlive)
{
}
or
t1.Join();
or
myAutoResetEvent.WaitOne(); // myAutoResetEvent.Set() called in thread when it finished processing
I am not sure but, this might not be a good example but looking forward to one.
I know that they are all some form of signaling from the background thread to inform the calling/UI thread that the work has completed.
But using them end up blocking the UI until the thread completes. So I would like to know a real life scenario implementation of this.
I am thinking why not just run this process on the UI thread since you don't mind blocking it.
Edit: In otherwords, I am looking for the real uses of these blocking elements such as thread.Join() etc
A real life scenario relevant to your example would be where the reference to the thread is stored in a member of the window class, and it gets checked or waited for if some event triggers such as closing the window or the application exiting.
pseudo code:
class Window
{
private Thread _thread = null;
public void OnButtonClick()
{
_thread = CreateAndStartThread();
}
public void OnCloseWindow()
{
if(null != _thread)
_thread.Wait();
}
}
I have the following code:
public class GUI
{
public void threadTask()
{
while(MY_GLOBAL_VARIABLE)
{
// do something
}
}
}
// Execute Thread
GUI gui = new GUI();
Thread t = new Thread(threadTask);
t.Start();
This seems like a messy way to do this. Any better approach how to reference it and kill it instantly? Thanks!
UPDATE: who ever gave me a downvote, LEARN TO READ! I clearly specified what I'm trying to 'kill' in the title, tags and code, at least next time read the post before casting a vote.
What you have is fine, the thread will be cleaned up as soon as it's finished processing.
You don't kill/dispose a thread, it has no IDisposable.
You could put the thread start in a method, so you can call it more then once, when it finished the first time.
You can use:
t.Join();
to catch when the thread finished.
The call to Join() is what de-allocates the thread. You don't have to do anything else. Just make sure that the threads clean up any resources they might be using before they exit.
I'm looking for a way to restart a thread that has been stopped by Abort()..
public partial class MyProgram : Form
{
private Thread MyThread = new Thread(MyFunction);
private System.Windows.Forms.Button startStopBtn = new System.Windows.Forms.Button();
public MyProgram()
{
MyThread.Start();
startStopBtn += new EventHandler(doStop);
startStopBtn.Text = "Stop";
}
private static void MyFunction()
{
// do something
}
private void doStop(object sender, EventArgs e)
{
MyThread.Abort();
startStopBtn -= new EventHandler(doStop);
startStopBtn += new EventHandler(doStart);
startStopBtn.Text = "Start";
}
private void doStart(object sender, EventArgs e)
{
MyThread.Start(); // << Error returned when clicking the button for 2nd time
startStopBtn -= new EventHandler(doStart);
startStopBtn += new EventHandler(doStop);
startStopBtn.Text = "Stop";
}
}
Any idea?
Once you have aborted your thread, you cannot start it again.
But your actual problem is that you are aborting your thread. You should never use Thread.Abort().
If your thread should be paused and continued several times, you should consider using other mechanisms (like AutoResetEvent, for example).
[EDIT]
The simplest solution to abort a thread, as mentioned by Ian Griffiths in the link above, is:
The approach I always recommend is dead simple. Have a volatile bool field that is visible both to your worker thread and your UI thread. If the user clicks cancel, set this flag. Meanwhile, on your worker thread, test the flag from time to time. If you see it get set, stop what you're doing.
The only thing that you need to do to make it work properly, is to rearrange your background method so that it runs in a loop - so that you can periodically check if your flag has been set by a different thread.
If you need to have pause and resume functionality for the same worker thread, instead of the simple volatile bool flag approach, you could go for a slightly more complex approach, a synchronizing construct such as AutoResetEvent. These classes also provide a way to put the worker thread to sleep for a specified (or indefinite) amount of time between signals from the non-worker thread.
This thread contains a concrete example with Start, Pause, Resume and Stop methods. Note how Brannon's example never aborts the thread. It only fires an event, and then waits until the thread finishes gracefully.
Simply add MyThread = new Thread(MyFunction) before calling MyThread.Start() in doStart(). Do not create the thread outside of your methods, the space there is thought for declarations.
Please note that killing a thread with thread.Abort() can be very dangerous, as it might cause unexpected behavior or might not correctly dispose resources owned by the thread. You should try to accomplish clean multi threading, like Groo described in his answer.
The simple answer is, you can't. Once a thread has been aborted, you can't restart it. Just create a method or something, that returns a Thread object just how you need it. When you need a new Thread, just get it from that method.
No, there isn't, but why would you want to? Just start up a new thread, with the same ThreadStart, and the same parameter (if any).
If you really need to interrupt the thread function and resume, you should set a condition and then check it periodically during processing.
That would allow you to stop processing for some amount of time and then resume.
I've used events and Wait calls to accomplish a similar task.
The easiest way is to not abort the thread.
I really don't understand why people provide information if they do not know that is correct..
How can a real programmer suspend or stop processing a thread for sometime and then release it and thereby making the code vulnerable...
#Brad-- m sorry.. but your idea was not good..
#Rhythmic - You need to work on your way to approach things..
BFree was somewhat right if you people got him the same way he wanted to say..
You just need to re-declare that..
below is the example:
Public Shared Sub ResetAbort()
Dim ThreadPleaseWait As New Thread(New ThreadStart(AddressOf YourSubName))
YourThreadName.Start()
Thread.Sleep(2000)
YourThreadName.Abort()
End Sub
Now you can use this Sub anywhere you want to start the thread. It will automatically abort the thread.
If you want to start the thread on Button1_click() event and stop it on Button2_Click() event use this:
in Button1_click() event
Dim ThreadPleaseWait As New Thread(New ThreadStart(AddressOf YourSubName))
YourThreadName.Start()
in Button2_click() event
YourThreadName.Start()
doing this way you will abort you thread where ever you want and will initialize it again.
You can also use YourThreadName.ThreadState.Running property to check if the thread is running or not(Just to avoid multiple instances of the same thread.....