what happens when we change the reference of a thread as null? - c#

I am running a while loop which keeps track of some events forever, In case if i get any exception i am changing its reference to null hoping that the current thread will be aborted and the new reference of that thread will be created. Is it correct or any better way to abort the current thread and start a newer one.
I am trying to do this:
Thread th;
Main()
{
th = new thread(myfunction);
th.Start();
}
void myfunction()
{
while(true)
{
try
{
// something interesting here.
}
catch(exception)
{
th = null;
}
}
}

Only thing that will happen is that Thread will remain inaccessible from the Enclosing class.
If there are no further processing, doing so will make the thread out of reach from GC appllication roots. This makes object available for garbage collection in next GC trigger.

You need to do:
return;
instead of:
th = null;
Because the thread will keep on running. The thread object will not get collected, since it will stay referenced as long as the code is running.

Clean up anything you need to for that thread, then break out of the while loop like this:
void runningOnThread()
{
while (true)
{
try
{
//...
}
catch (Exception e)
{
break;
}
}
//thread cleanup code goes here, if you have any.
}
It would be a good idea to log the exception when you catch it. That way you know when you've hit an exception.

First, if you run into an exception, before worrying about starting a new thread, be sure that you actually handle the exception and ensure that the restarted thread will be able to run successfully. Otherwise, you're just going to get a constant stream of crashing threads, and a choppy program while it handles the exception parade. Just some food for thought.
Now, answering the question, best case nulling the reference to the thread will just leave you in an infinite loop, worst case you try to use 'th' later and you get an exception because it's null. Nulling the reference to the thread won't somehow make it aware that it needs to restart itself any more than nulling a reference to parameter you gave it as a function argument will. If you absolutely need some kind of ability to abort/restart the thread, look into doing one of:
raising an event when the thread crashes and break out of the while loop, or
setting a boolean/enum flag saying what the thread is doing, and have the main thread check on it every so often to make sure it hasn't been set to the error state.
This is code is completely off the top of my head, isn't that good, but will give you the general idea:
delegate void ThreadCrashedEvent();
Event ThreadCrashedEvent threadCrashed;
Thread th;
Main()
{
threadCrashed += OnThreadCrashed();
th = new thread(myfunction);
th.Start();
}
void OnThreadCrashed()
{
th = new thread(myfunction);
th.Start();
}
void myfunction()
{
while(true)
{
try
{
LetsGetDangerous();
}
catch(exception)
{
if(threadCrashed != null)
{
threadCrashed();
return;
}
}
}

Related

Detecting if Thread is Alive, or not, with while loop in the safest way c#

I am trying to end my Thread, within the thread, and when aborted, i want to detect that the thread has been aborted (or just, stopped really)
This is what i am doing to do that, but isnt working as it never gets to this part
if (!thread.IsAlive){
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
This is how i'm going about it, thank you for the help. sorry if my question is confusing please ask questions so i can help you help me :) thanks!
public static Thread thread;
public static void 1()
{
thread = new Thread(thread1);
thread.Start();
if (!thread.IsAlive)
{
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
public static void thread1()
{
{
int test = 0;
while (thread.IsAlive){
Console.WriteLine("running.."); // this text will be displayed when the thread is active, and will stop when stopped.
Thread.Sleep(2500);
test += 1;
if (test > 4) // after 4 loops, i want the thread to end itself
thread.Abort();
}
if (!thread.IsAlive){ // once the thread is ended i want it to tell us that, but it never gets to this part.
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
}
If you want to check if a thread is still alive, you cannot do that from the code running in that particular thread. Because, if you can execute the code to check if the thread is still alive, it is -- obviously -- still alive. And if the thread is not alive anymore it will -- obviously -- not be able to execute any more code ...
So the only way is to do this from somewhere outside the thread (ie some other thread, maybe even the main thread).
Just schematic code, which is rather clumsy, but will give you a first idea of how you can address this issue. But if there is a third party messing around with your threads, that won't help anything, because what prevents them from killing off your whole application?
public class ThreadTest {
static bool ranToEnd = false;
public static void Main(){
var thread = new Thread(aThread);
var lc = 1;
thread.Start();
while (true){
if (!aThread.IsAlive) {
if (ranToEnd)
Console.WriteLine("aThread terminated normally");
else
Console.WriteLine("aThread ended prematurely");
break;
} else if (++lc == 10) {
aThread.Abort(); //Simulating the abortion of the thread
}
Thread.Sleep(1000);
}
}
public static void aThread() {
//do some work in this thread
// if the thread ran to an end normally, this will be set to true
// if the thread ended prematurely, this will stay false ...
ranToEnd = true;
}
}

A thread is still trying to access a disposed form?

Basically, I have a thread that downloads and reports the download status to a progress bar and a label. It always crashes when trying to invoke a object in a disposed form (Progress bar & label) even when there's a if (!this.Disposed) is called before, and still throws the exception even with a catch (ObjectDisposedException) is called in the same try block. I'm not sure what I can do to fix this, it's probably best described as the most annoying thing I've ever encountered.
Thanks you.
Update (from a considerate SO lurker) of my source found on pastebin
Thread downloader();
public bool abortThread = false();
private void frmDownload_FormClosing(object sender, FormClosingEventArgs e) {
downloader.Abort(); // Abort the thread before closing the form...?
abortThread = true; // Set the abortThread to true
this.Dispose(); // Dispose thread
}
downloader = new Thread(() => {
string[] URLs = { "http://test1.com/", "http://test2.com/", "http://test3.com/" };
try {
using (WebClient wc = new WebClient()) {
wc.DownloadProgressChanged += (s, e) => {
if (!pbDownloadStatus.IsDisposed && !lbPercentage.IsDisposed) {
if (!abortThread) {
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value = e.ProgressPercentage)); // EXCEPTION HAPPENS HERE
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value++));
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value--));
this.Invoke((MethodInvoker)(() => lbPercentage.Text = e.ProgressPercentage.ToString() + "%"));
}
}
};
wc.DownloadFileCompleted += (s, e) => {
if (!pbDownloadStatus.IsDisposed && !lbPercentage.IsDisposed) {
lock (e.UserState) {
this.Invoke((MethodInvoker)(() => pbDownloadStatus.Value = 0));
this.Invoke((MethodInvoker)(() => lbPercentage.Text = "0%"));
Monitor.Pulse(e.UserState);
}
}
};
wc.Proxy = WebProxy.GetDefaultProxy();
wc.Headers.Add(header);
for (int i = 0; i < URLs.Length; i++) {
var sync = new Object();
lock (sync) {
wc.DownloadFileAsycn(new Uri(URLs[i]), "C:\Test\URL" + i);
Monitor.Wait(sync);
}
}
}
}
}
catch (ObjectDisposedException disEx) { // Never gets caught
downloader.Abort();
MessageBox.Show("Object was disposed");
}
});
downloader.Start();
From Msdn
Beginning with the .NET Framework 4, multithreaded programming is
greatly simplified with the System.Threading.Tasks.Parallel and
System.Threading.Tasks.Task classes, Parallel LINQ (PLINQ), new
concurrent collection classes in the System.Collections.Concurrent
namespace, and a new programming model that is based on the concept of
tasks rather than threads
The need to work with threads directly in the modern era is greatly reduced, and you should probably look at Tasks and async/await Tasks can be cancelled, are easier to manage and async returns back to the calling context.
Secondly, your code doesn't make sense, and its full of compiler errors which is not a good start for a question. Additionally, since there is so much wrong with the code i have decided to just give you lots of points to think about apposed to rewriting it all
So lets look at some of the more obvious issues this code has.
abortThread is accessed from multiple threads and is not thread safe for the most part.
You are calling var sync = new Object(); directly before lock (sync) meaning you are locking nothing
Even if that lock statement was going to work, there is no other thread using the lock, meaning its redundant.
You are calling this.Dispose() from the forms closing event. This is unusal to say the least
The two conditions when a form is not disposed on Close is when (1) it
is part of a multiple-document interface (MDI) application, and the
form is not visible; and (2) you have displayed the form using
ShowDialog. In these cases, you will need to call Dispose manually to
mark all of the form's controls for garbage collection.
Basically in a non MDI application, If you call ShowDialog then put it in a using statement.
You are trying to check IsDisposed to determine if its safe to marshal back to the UI thread.
Just because you call Dispose doesn't mean the form IS disposed, this is not how it works and will not solve your problem.
If you need to do asynchronous IO bound work, Use the aysnc,await pattern, then you wont be blocking a thread for spurious reasons waiting for a completion port. If you need to run this in parallel, then consider DataFlow with action blocks so you can take advantage of aysnc,await and parallel.
If you need to determine whether a form is alive or dead, use a thread safe variable. Use a static Lock object, and every where you update the variable use lock as well.
if you need to marshal to the UI thread. Don't do this.Invoke((MethodInvoker)(() multiple times, Do it once, and update everything at once.

thread suicide question

I want to kill a thread when something very bad happen. What's your suggestion to do thread suicide?
You should never actually "kill" a thread. From your main program, you can abort it using the Thread.Abort method, but this is not recommended, and it is completely unnecessary.
Your thread should be nothing more than a method executing a long loop. If something "really bad" happens, simply return from this method and thread will end.
This would be enough for such a loop:
private void MyThreadLoop()
{
try
{
while (someCondition)
{
// do a lengthy operation
}
}
catch (Exception ex)
{
Log.Error("Something bad happened: ", ex);
}
}
public void Start()
{
Thread t = new Thread(MyThreadLoop);
t.Start()
}
On the other hand, if you need your main program to kill the thread (but this is not a "suicide" as you named it), then you should signal the thread that you want it to end, and not abort it without knowing what is going on in the background.
There's no need to completely kill a thread, all you need to do is have it stop working on the current task.
Inside of thread, its enough to return from its function. Outside of thread, there is method Thread.Abort().
You could try something like this. The thread runs until it receives a signal from "outside" and then exists.
private static void Main(string[] args)
{
var shouldExit = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(
delegate
{
while (true)
{
Console.WriteLine("Running...");
if (shouldExit.WaitOne(0)) break;
}
Console.WriteLine("Done.");
});
// wait a bit
Thread.Sleep(1000);
shouldExit.Set();
Console.ReadLine();
}

How to abort a thread started inside another function?

Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,200));
t.Start();
I start a thread named 't' inside the 'Form1_Load' function. I have added a button. When click on that button the thread 't' should stop executing and create a new thread with these parameters.
Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,950));
t.Start();
I know in the form_load event i can use the
t.Abort();
By making t a member of the form, you can reference it later on in the button-click event handler.
Graceful Abort.
Although t.Abort() gets the job done, you might be left with half-processed data in the thread t. You can catch the ThreadAbortException in thread t to gracefully end processing.
Beware of overlap.
The second problem is that your thread might not have aborted yet while your new thread has started already. You can prevent that by calling t.Join() after calling t.Abort().
Hope this helps.
Make Thread t a private member of your form.
public partial class MainForm : Form
{
private Thread t;
}
One way is to make Thread t a global variable (place outside of Form_Load). Then it can be accessed and modified from any method in that class.
To instantiate the thread, use t = new Thread(.....
Before aborting the thread, make sure it is not null.
You need to make the Thread object accessable in both places that you need to access it.
In this case, making it a private varaible would work.
e.g.
public class MyClass
{
private Thread MyThread
{
get;
set;
}
private void myfunc1()
{
MyThread = new Thread(() => moni.CurrUsage(nics,200));
MyThread.Start();
}
private void myfunc2()
{
MyThread.Abort();
// I really need to wait until this thread has stopped...
MyThread.Join();
}
}
Adding to the already given answers:
Note that .Join() will block your current (UI) thread, leaving your application unresponsive to the user.
Just as another take: avoid using .Abort() by using a flag in your Monitor class to exit the task you are doing if possible. You can then still wait for .Join(), but you have full control of the state in the background thread.
public class Monitor
{
private bool _cancel = false;
public void Cancel()
{
_cancel = true;
}
public void CurrUsage(Nics nics, int n)
{
_cancel = false;
// ...
while (!_cancel)
{
// do some stuff
}
}
}
in your Form
private Monitor _monitor { get; set; }
private Thread _t;
public void Button_Click(...)
{
_monitor.Cancel()
_t.Join() // will return as your background thread has finished cleanly
_t = new Thread(() => _monitor.CurrUsage(nics,950));
t.Start();
}
As others have pointed out, all you need in order to call Abort is a reference to the thread (just like any other object in .NET).
However
You should seriously consider rethinking this approach. In general, calling Abort is discouraged, as it does not give the target thread sufficient opportunity to reach a stopping point. While it's sometimes appropriate (or the only option), it's almost always a better idea to ask the target thread to stop (usually through a volatile bool rather than forcing it like this.
For example,
public class ThreadClass
{
private volatile bool stopRequested;
private Thread thread;
public void Start()
{
stopRequested = false;
thread = new Thread(ThreadMethod);
thread.Start();
}
public void Stop()
{
stopRequested = true;
if(!thread.Join(5000)) thread.Abort(); // forcefully abort if not
// completed within 5 seconds
}
private void ThreadMethod()
{
}
}
Your code then goes into ThreadMethod. Within the method, periodically check the value of stopRequested. If it's true, perform whatever cleanup is necessary (if any) and gracefully return out of the thread. If the content is a loop, the general practice is to place the check at the start of the loop (assuming that the loop is sufficiently tight) and exit early if the value is true. The exact placement is really dependent upon the code, but the general idea is that it should be checked often enough to make the thread exit fairly quickly after it gets set, regardless of when that happens.

Avoid calling Invoke when the control is disposed

I have the following code in my worker thread (ImageListView below is derived from Control):
if (mImageListView != null &&
mImageListView.IsHandleCreated &&
!mImageListView.IsDisposed)
{
if (mImageListView.InvokeRequired)
mImageListView.Invoke(
new RefreshDelegateInternal(mImageListView.RefreshInternal));
else
mImageListView.RefreshInternal();
}
However, I get an ObjectDisposedException sometimes with the Invoke method above. It appears that the control can be disposed between the time I check IsDisposed and I call Invoke. How can I avoid that?
What you have here is a race condition. You're better off just catching the ObjectDisposed exception and be done with it. In fact, I think in this case it is the only working solution.
try
{
if (mImageListView.InvokeRequired)
mImageListView.Invoke(new YourDelegate(thisMethod));
else
mImageListView.RefreshInternal();
}
catch (ObjectDisposedException ex)
{
// Do something clever
}
There are implicit race conditions in your code. The control can be disposed between your IsDisposed test and the InvokeRequired test. There's another one between InvokeRequired and Invoke(). You can't fix this without ensuring the control outlives the life of the thread. Given that your thread is generating data for a list view, it ought to stop running before the list view disappears.
Do so by setting e.Cancel in the FormClosing event and signaling the thread to stop with a ManualResetEvent. When the thread completes, call Form.Close() again. Using BackgroundWorker makes it easy to implement the thread completion logic, find sample code in this post.
The reality is that with Invoke and friends, you can't completely protect against invoke on a disposed component, or then getting InvalidOperationException because of the missing handle. I haven't really seen an answer yet, like the one farther below, in any of the threads that addresses the real fundamental problem, which cant be completely solved by preemptive testing or using lock semantics.
Here's the normal 'correct' idiom:
// the event handler. in this case preped for cross thread calls
void OnEventMyUpdate(object sender, MyUpdateEventArgs e)
{
if (!this.IsHandleCreated) return; // ignore events if we arn't ready, and for
// invoke if cant listen to msg queue anyway
if (InvokeRequired)
Invoke(new MyUpdateCallback(this.MyUpdate), e.MyData);
else
this.MyUpdate(e.MyData);
}
// the update function
void MyUpdate(Object myData)
{
...
}
The fundemental problem:
In using the Invoke facility the windows message queue is used, which places a message in the queue to either wait or fire-and-forget the cross thread call exactly like Post or Send message. If there is a message ahead of the Invoke message that will invalidate the component and its window handle, or that got placed just after any checks you try to perform, then you are going to have a bad time.
x thread -> PostMessage(WM_CLOSE); // put 'WM_CLOSE' in queue
y thread -> this.IsHandleCreated // yes we have a valid handle
y thread -> this.Invoke(); // put 'Invoke' in queue
ui thread -> this.Destroy(); // Close processed, handle gone
y thread -> throw Invalid....() // 'Send' comes back, thrown on calling thread y
There is no real way to know that the control is about to remove itself fromthe queue, and nothing really reasonable you can do to "undo" the invoke. No matter how many checks you do or extra locks you make, you cant stop someone else form issuing something like a close, or deactivate. There are tons of senarios where this can happen.
A solution:
The first thing to realize is that the invoke is going to fail, no different than how a (IsHandleCreated) check would have ignored the event. If the goal is to protect the caller on the non-UI thread you will need to handle the exception, and treat it like any other call that didn't succeed (to keep app from crashing or do whatever. And unless going to rewrite/reroll Invoke facility, the catch is your only way to know.
// the event handler. in this case preped for cross thread calls
void OnEventMyWhatever(object sender, MyUpdateEventArgs e)
{
if (!this.IsHandleCreated) return;
if (InvokeRequired)
{
try
{
Invoke(new MyUpdateCallback(this.MyUpdate), e.MyData);
}
catch (InvalidOperationException ex) // pump died before we were processed
{
if (this.IsHandleCreated) throw; // not the droids we are looking for
}
}
else
{
this.MyUpdate(e.MyData);
}
}
// the update function
void MyUpdate(Object myData)
{
...
}
The exception filtering can be tailored to suit whatever the needs are. Its good to be aware that worker threads often dont have all the cushy outer exception handling and logging the UI threads do, in most applicaitons, so you may wish to just gobble up any exception on the worker side. Or log and rethrow all of them. For many, uncaught exceptions on worker thread means the app is going to crash.
Try using
if(!myControl.Disposing)
; // invoke here
I had the exact same problem as you. Ever since I switched to checking .Disposing on the control, the ObjectDisposedException has gone away. Not saying this will fix it 100% of the time, just 99% ;) There is still a chance of a race condition between the check to Disposing and the call to invoke, but in the testing I've done I haven't ran into it (I use the ThreadPool and a worker thread).
Here's what I use before each call to invoke:
private bool IsControlValid(Control myControl)
{
if (myControl == null) return false;
if (myControl.IsDisposed) return false;
if (myControl.Disposing) return false;
if (!myControl.IsHandleCreated) return false;
if (AbortThread) return false; // the signal to the thread to stop processing
return true;
}
may be lock(mImageListView){...} ?
You could use mutexes.
Somewhere at the start of the thread :
Mutex m=new Mutex();
Then :
if (mImageListView != null &&
mImageListView.IsHandleCreated &&
!mImageListView.IsDisposed)
{
m.WaitOne();
if (mImageListView.InvokeRequired)
mImageListView.Invoke(
new RefreshDelegateInternal(mImageListView.RefreshInternal));
else
mImageListView.RefreshInternal();
m.ReleaseMutex();
}
And whereever it is you are disposing of mImageListView :
m.WaitOne();
mImageListView.Dispose();
m.ReleaseMutex();
This should ensure you cant dispose and invoke at the same time.
See also this question:
Avoiding the woes of Invoke/BeginInvoke in cross-thread WinForm event handling?
The utility class that resulted EventHandlerForControl can solve this problem for event method signatures. You could adapt this class or review the logic therein to solve the issue.
The real problem here is that nobugz is correct as he points out that the APIs given for cross-thread calls in winforms are inherently not thread safe. Even within the calls to InvokeRequired and Invoke/BeginInvoke themselves there are several race conditions that can cause unexpected behavior.
If a BackGroundWorker is a possibility, there's a very simple way to circumvent this:
public partial class MyForm : Form
{
private void InvokeViaBgw(Action action)
{
BGW.ReportProgress(0, action);
}
private void BGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (this.IsDisposed) return; //You are on the UI thread now, so no race condition
var action = (Action)e.UserState;
action();
}
private private void BGW_DoWork(object sender, DoWorkEventArgs e)
{
//Sample usage:
this.InvokeViaBgw(() => MyTextBox.Text = "Foo");
}
}
Handle the Form closing event. Check to see if your off UI thread work is still happening, if so start to bring it down, cancel the closing event and then reschedule the close using BeginInvoke on the form control.
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if (service.IsRunning)
{
service.Exit();
e.Cancel = true;
this.BeginInvoke(new Action(() => { this.Close(); }));
}
}
The solution proposed by Isak Savo
try
{
myForm.Invoke(myForm.myDelegate, new Object[] { message });
}
catch (ObjectDisposedException)
{ //catch exception if the owner window is already closed
}
works in C# 4.0 but for some reasons it fails in C#3.0 (the exception is raised anyway)
So I used another solution based on a flag indicating if the form is closing and consequently preventing the use of invoke if the flag is set
public partial class Form1 : Form
{
bool _closing;
public bool closing { get { return _closing; } }
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_closing = true;
}
...
// part executing in another thread:
if (_owner.closing == false)
{ // the invoke is skipped if the form is closing
myForm.Invoke(myForm.myDelegate, new Object[] { message });
}
This has the advantage of completely avoiding the use of try/catch.
One way might be to call the method itself ones more instead of invoking the ImageListView-Method:
if (mImageListView != null &&
mImageListView.IsHandleCreated &&
!mImageListView.IsDisposed)
{
if (mImageListView.InvokeRequired)
mImageListView.Invoke(new YourDelegate(thisMethod));
else
mImageListView.RefreshInternal();
}
That way it would check one more time before finally calling RefreshInternal().
The suggestion to stop the thread generating the messages is not acceptable. Delegates can be multicast. Because one listener does not want to listen to the band, you don't shoot the band members.
Since the framework doesn't provide any easy way I know of to clear the message pump of those event messages, and since the form does not expose its private property that lets us know the form is closing:
Set a flag on the IsClosing Event of the window after you unsubscribe or stop listening to the events, and always check this flag before you do a this.Invoke().
i have same error. my error occurred in thread. finally i write this method :
public bool IsDisposed(Control ctrl)
{
if (ctrl.IsDisposed)
return true;
try
{
ctrl.Invoke(new Action(() => { }));
return false;
}
catch (ObjectDisposedException)
{
return true;
}
}
This works for me
if (this.IsHandleCreated){
Task.Delay(500).ContinueWith(_ =>{
this.Invoke(fm2);
});
} else {
this.Refresh();
}

Categories

Resources