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.
Related
I'm writing a application with a critical region.
And I decide to use AutoResetEvent to achieve mutual exclusion.
Here's the code
public class MyViewModel
{
private AutoResetEvent lock = new AutoResetEvent(true);
private aync Task CriticalRegion()
{
Dosomething();
}
public async Task Button_Click()
{
Debug.WriteLine("Entering Button_Click");
lock.WaitOne();
try
{
await CriticalRegion();
}
finally
{
lock.Set();
Debug.WriteLine("Leaving Button_Click");
}
}
}
I have a button whose click event calls the Button_Click() method
It works normally. But, if I'm quick enough to click the button for another time before the first call to Button_Click() completes, the whole app stops responding.
In the Debug window I find something like this
Entering Button_Click
Entering Button_Click
Looks like the method never completes.
I struggled a bit and find that if I change lock.WaitOne(); to
if (!sync.WaitOne(TimeSpan.FromSeconds(1)))
{
return;
}
In this case my app is able to avoid the deadlock,but I don't know why it works.
I only know about the IPC from my OS course and the async and await pattern in C#, and I'm not so familiar with the thread in .Net world.
I really want to understand what's really going on behind the scenes.
Thanks for any replys ;)
You have a deadlock because WaitOne is blocking the main thread (button click handler is executed on the main thread), while you haven't called ConfigureAwait(false) when calling await, which means that it tries to run the code which is after await on the main thread, even if it's blocked, which would causes a deadlock.
I suggest reading this post for a thorougher explanation of the dead lock situation.
For your code, I would suggest putting the lock deeper, probably within the async Task, and trying to use a more suitable pattern for locking, preferably, the lock statement, because using Event objects is awkward for mutual exclusion, as Hans stated in the comment.
AutoResetEvent.WaitOne() will block infinitely until you call AutoResetEvent.Set(), which you never seem to do except for after the WaitOne() call.
Quoting the AutoResetEvent.WaitOne() documentation:
Blocks the current thread until the current WaitHandle receives a signal.
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.
I have a thread:
void threadCode(object o)
{
doStuffHere(o); // Blocking call. Sometimes hangs.
}
and I'm calling it like this:
Thread t = new Thread(new ThreadStart(delegate()
{
threadCode(o);
}));
t.Start();
StopWatch sw = new StopWatch();
sw.Start();
while (t.IsAlive)
{
Application.DoEvents();
if (sw.EllapsedMilliseconds > myTimeout)
// Somehow kill t even though doStuffHere(o) is blocked (but hung)
}
I'm using the .NET Zip Library and calling ZipFile.CommitUpdate() which works most of the time, but sometimes just hangs. I don't know why, I can't see anything in the documentation which specifies why this is happening. A small file which should take no longer than 5 - 10 seconds will sometimes sit there for more then 5 minutes with no progress. I/O graphs in process explorer show that the process is not reading or writing, and there is no CPU usage. Basically, if this happens, I want to kill CommitUpdate() and try again once or twice before giving up.
Any idea how I can kill a thread stuck in a blocking call?
(Alternatively - those of you with experience with this zip library: do you know why it might be hanging with some files sometimes? I'm modifying the contents of .docx and .pptx (GZip) files. This would be an ideal solution.)
If you're going to terminate the hanging thread by using Thread.Abort(), make sure you handle ThreadAbortException in your thread code. The normal pattern is:
try {
// do work here
}
catch (ThreadAbortException) {
// allows your thread to gracefully terminate
Thread.ResetAbort();
}
catch {
// regular exception handling
}
If you don't follow the above pattern, then at best your threads will terminate ungracefully. At worst, you could run into a number of other problems.
You can call Thread.Abort to bloodily murder the thread.
The thread will not be able to clean up after itself (except for finally blocks); depending on exactly what it was doing at the time, it could seriously mess up your program.
DO NOT use Thread.Abort() to workaround a bug in a library you're using. (Or it could be a bug in your code).
Either get the original bug fixed, or move to a different library.
ps: You might want to try DotNetZip, in lieu of SharpZipLib.
Alternative to using a Stopwatch, you could do this:
Thread thread = new Thread(new ThreadStart(delegate()
{
threadCode(o);
}));
thread.Start();
thread.Join(myTimeout);
if(thread.IsAlive)
{
thread.Abort();
}
Use the Thread.Abort() method to kill a thread. See http://msdn.microsoft.com/en-us/library/aa332365(VS.71).aspx for more details.
As a last resort you could use Thread.Abort() to terminate the thread - don't expect any orderly shutdown.
I haven't done this myself, so I not sure about this, but does t.Abort(); do the trick?
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.....
I am using a background thread to initialize an instrument over USB. The UI hangs when I try to open the device. I would expect the background thread to pause when calling Open on the device, but not the UI thread. I am testing this with no UI interaction from the background thread. I don't know how to debug the problem, and it's too broad a question, but perhaps someone has seen something like this before. There is nothing wrong with the ActiveX interop as far as I know, the device works correctly. This is the general approach:
using System;
using FancyVoltmeterLibrary;
namespace SOQuestion
{
public class MeterClass
{
private FancyVoltmeter meter;
private Thread meterThread;
public MeterClass()
{
// Create instance of ActiveX/COM object.
meter = new FancyVoltmeter();
meterThread = new Thread(UpdateMeter);
meterThread.Name = "Meter Thread";
meterThread.Priority = ThreadPriority.Normal;
meterThread.IsBackground = true;
meterThread.Start();
}
private void UpdateMeter()
{
while(true)
{
Thread.Sleep(1000);
if(!meter.IsOpen())
{
// Meter may be powered off here.
// The call to Open takes about 1 second.
// UI hangs during the call???
meter.Open();
}
// code to read meter goes here.
}
}
}
}
Edit: Perhaps unclear what I meant. By 'hang' I should say 'freezes momentarily'.
Does meter require running in an STA? Is the call to Open() actually being marshalled back to the UI thread for this reason?
You can verify this is true by looking at the callstack of the hung UI thread in the debugger.
How long time does the instantiation of the FancyVoltmeter take? Could it be that it is not the Open method that causes the UI freeze, but creating the COM object (which is done on the UI thread)?
If that turns out to be the case, moving the creation of this object to happen on the new, separate worker thread should take care of the problem.
Edit: I saw now that you already found this out in your comment to Michael...
I would suggest you wrap the call to meter.open() in a separate method, and call that method from within the updateMeter() method using Invoke() or BeginInvoke() construct on the form or parent control. Doing this will marshal the action back on to the UI thread and should execute gracefully. I hope this helps.
Consider using a BackgroundWorker for this task.