How to find out when a specific thread exits (C#)? - c#

I have a problem here. Is there a way to programmatically find out the moment a certain thread exits? I mean, even the VS debugger gives you that info in its Output window. I know that I simply could make my thread to raise an event but this of course leads to a problem when you spawn more than one thread, so each of them will raise that event, unless you use some toggle variable to make sure that only the first thread to reach that point in code will raise the event.
Here is the beginning of a method that is executed in multiple threads, with cancellation, pause and exit logic shown here. The problem spots of code are the calls to the event handlers (DownloadComplete, DownloadPaused and DownloadCanceled). As you can see, some of them will be executed only once by the first thread that reaches that point and then toggles related bool variables, so other threads won't raise this event again. Another big problem here is the thread exit logic, when the thread doesn't find an item to download and returns with rasing that download complete event which of course will be fired by each thread. Both of these approaches are incorrect and I currently have no any idea how to implement my intended behavior. All I need is to have a clue how to find out a way to catch the momement when the last of the all of spawned thread ends so I could raise all of the mentioned above events just once.
Please note that I have no acess to the types from the System.Threading.Tasks namespace as my project is targeted against .net 2.0. This is my very first experiece with programming something more complex than some class assignment, so I realize that this code is most likely all sorts of terrible.
Sorry for my English.
private void PerformDownload()
{
while (true)
{
if (askedToCancel)
{
lock (lockObj)
{
if (!cancellationPerformed)
{
cancellationPerformed = true;
foreach (DownloadItem di in itemsToProcess)
if (di.Status == DownloadItemStatus.Prepared)
itemsToProcess.UpdateItemStatus(di.URL, DownloadItemStatus.Canceled);
DownloadCanceled();
}
}
return;
}
if (askedToPause)
{
lock (lockObj)
{
if (!pausingPerformed)
{
foreach (DownloadItem di in itemsToProcess)
if (di.Status == DownloadItemStatus.Prepared)
itemsToProcess.UpdateItemStatus(di.URL, DownloadItemStatus.Paused);
DownloadPaused();
}
}
waitHandle.WaitOne();
}
DownloadItem currentItem = null;
lock (lockObj)
{
foreach (DownloadItem di in itemsToProcess)
if (di.Status == DownloadItemStatus.Prepared)
{
currentItem = di;
itemsToProcess.UpdateItemStatus(currentItem.URL, DownloadItemStatus.Downloading);
break;
}
}
if (currentItem == null)
{
DownloadComplete();
return;
}

You can use Interlocked.Increment() and Interlocked.Decrement() on a counter, incrementing at the thread's entry point, decrementing when the thread exits. Then if the counter is non-zero, at least one instance of that thread is running.
For example:
private int _threadCounter;
private void ThreadEntryPoint()
{
try
{
Interlocked.Increment(ref _threadCounter);
// Do thread stuff here
}
finally
{
Interlocked.Decrement(ref _threadCounter);
}
}
That said, it is IMHO not likely to be the best design for it to matter whether the thread is running or not. That is, whenever I think of how that information might be used, it seems to me there's a better way to address the scenario.
Threads exist for a reason, beyond simply being present. So what your code really ought to care about is whether that reason has been addressed, not whether any thread is running. Without a complete code example, I can't really comment on a specific scenario. But I suspect that tracking the actual thread existence is less useful and will be harder to maintain than a more goal-oriented approach.

Related

Lock hangs when called from UI to System.Threading.Thread

EDIT:
please see question history, for unchanged question in order not to invalidate comments.
I am clicking button that executes certain codes and it creates a thread (System.Threading.Thread). When I reclick button which starts process it hangs and freezes ui. What could be the reason?
public partial class ucLoader : UserControl
{
//lock object for whole instance of class ucLoader
private object lockUcLoader = new object();
//bringing info from ui
private void btnBringInfo_Click(object sender, EventArgs e)
{
lock (lockUcLoader)
{
btnBringInfo_PerformClick(false);
}
}
//using this method because it could be called when even button not visible
internal void btnBringInfo_PerformClick(bool calledFromBandInit)
{
lock (lockUcLoader) //HANGS HERE when called multiple times and ui freeze as well
//by the way I am using (repetitive) lock, because this method also called independently from btnBringInfo_Click
{
//...
this.btnLoad_PerformClick();
}
}
//Another button perform click that could be triggered elsewhere when even button not visible
private void btnLoad_PerformClick()
{
lock (lockUcLoader) //I am using (repetitive) lock, because this method also called independently from btnBringInfo_PerformClick
{
//...
Run();
}
}
//method for creating thread which System.Threading.Thread
private void Run()
{
lock (lockUcLoader) //Maybe this lock is NOT REQUIRED, as it is called by only btnLoad_PerformClick(), could you please confirm?
{
//some code that thread can be killed when available, you can ingore this two lines as they are irrelevant to subject, I think
Source = new CancellationTokenSource();
Token = Source.Token;
var shell = new WindowsShell();
Thread = new Thread((object o) =>
{
//...
var tokenInThread = (CancellationToken)o;
exitCode =TaskExtractBatchFiles(cls, shell, exitCode);
using (var logEnt = new logEntities())
{
//Do some db operation
//...
this.Invoke((MethodInvoker)delegate
{
//do some ui update operation
//...
});
}
}
Thread.Start(Token);
}
}
public void Progress(string message)
{
Invoke((MethodInvoker)delegate //ATTENTION HERE see below picture Wait occurs here
{
if (message != null && message.Trim() != string.Empty)
{
this.txtStatus.AppendText(message + Environment.NewLine);
}
});
}
}
In order to avoid get closed question, what my question is how can I prevent
below method can be accesses with out lock from background thread and ui thread
public void Progress(string message)
{
Invoke((MethodInvoker)delegate //ATTENTION HERE see below picture Wait occurs here
{
if (message != null && message.Trim() != string.Empty)
{
this.txtStatus.AppendText(message + Environment.NewLine);
}
});
}
Invoke((MethodInvoker)delegate ...
Whenever you use the lock statement in your code then you always run the risk of inducing deadlock. One of the classic threading bugs. You generally need at least two locks to get there, acquiring them in the wrong order. And yes, there are two in your program. One you declared yourself. And one you cannot see because it is buried inside the plumbing that makes Control.Invoke() work. Not being able to see a lock is what makes deadlock a difficult problem to debug.
You can reason it out, the lock inside Control.Invoke is necessary to ensure that the worker thread is blocked until the UI thread executed the delegate target. Probably also helps to reason out why the program deadlocked. You started the worker thread, it acquired the lockUcLoader lock and starts doing its job, calling Control.Invoke while doing so. Now you click the button before the worker is done, it necessarily blocks. But that makes the UI thread go catatonic and no longer capable of executing the Control.Invoke code. So the worker thread hangs on the Invoke call and it won't release the lock. And the UI thread hangs forever on the lock since the worker can't complete, deadlock city.
Control.Invoke dates from .NET 1.0, a version of the framework that has several serious design mistakes in code related to threading. While meant to be helpful, they just set death-traps for programmers to blunder into. What is unique about Control.Invoke is that it is never correct to use it.
Distinguish Control.Invoke and Control.BeginInvoke. You only ever need Invoke when you need its return value. Note how you don't, using BeginInvoke instead is good enough and instantly solves the deadlock. You'd consider Invoke to obtain a value from the UI so you can use it in the worker thread. But that induces other major threading issue, a threading race bug, the worker has no idea what state the UI is in. Say, the user might be busy interacting with it, typing a new value. You can't know what value you obtain, it will easily be the stale old value. Inevitably producing a mismatch between the UI and the work being done. The only way to avoid that mishap is to prevent the user from typing a new value, easily done with Enable = false. But now it no longer makes sense to use Invoke, you might as well pass the value when you start the thread.
So using BeginInvoke is already good enough to solve the problem. But that is not where you should stop. There is no point to those locks in the Click event handlers, all they do is make the UI unresponsive, greatly confuzzling the user. What you must do instead is set the Enable properties of those buttons to false. Set them back to true when the worker is done. Now it can't go wrong anymore, you don't need the locks and the user gets good feedback.
There is another serious problem you haven't run into yet but you must address. A UserControl has no control over its lifetime, it gets disposed when the user closes the form on which it is hosted. But that is completely out of sync with the worker thread execution, it keeps calling BeginInvoke even though the control is dead as a doornail. That will make your program bomb, hopefully on an ObjectDisposedException. A threading race bug that a lock cannot solve. The form has to help, it must actively prevent the user from closing it. Some notes about this bug in this Q+A.
For completeness I should mention the third most common threading bug that code like this is likely to suffer from. It doesn't have an official name, I call it a "firehose bug". It occurs when the worker thread calls BeginInvoke too often, giving the UI thread too much work to do. Happens easily, calling it more than about thousand times per second tends to be enough. The UI thread starts burning 100% core, trying to keep up with the invoke requests and never being able to catch up. Easy to see, it stops painting itself and responding to input, duties that are performed with a lower priority. That needs to be fixed the logical way, updating UI more than 25 times per second just produces a blur that the human eye can't observe and is therefore pointless.

Only need the first task, ignore the rest

I want to call a task at a specified interval. And avoid calling a new task unless the last has already completed.
private async void OnTimerTick(object sender, object e)
{
if (_criticalSection.IsEntered()) return; // only allow 1 at any given time, ignore the rest
using (var section = await _criticalSection.EnterAsync())
{
await update();
}
}
How do I achieve this? Any suggestions for a better pattern?
A critical section (like a Window's mutex) is for mutual exclusion: only allowing a single thread into a code path.
But that's not what you are trying to do: you need something that will tell you if something is happening.
A better approach would be a Manual Reset Event: set it (also know as signalled) at the start of the task and reset at the end. Then you can check if it is signalled by waiting on it with a timeout of zero for a normal Window's event, or with the applicable member for other types of event.
As this appears to be all in a single process a good starting point is System.Threading.ManualRestEventSlim. Used something like:
// One off initialisation somewhere at class scope
private static ManualResetEventSlim taskRunning = new ManualResetEventSlim();
private static object taskLock = new Object();
// code called from the timer, do in a lock to avoid race conditions with two
// or more threads call this.
lock (taskLock) {
if (!taskRunning.IsSet) {
StartTheTask(); // assuming this does not return until task is running.
}
}
// At the outermost scope of the code in the task:
try {
Debug.Assert(!taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Set();
// Task impementation
} finally {
Debug.Assert(taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Reset();
}
Another approach would be to always start the task, but have it check the event, if set then immediately exit. This would still need the lock to avoid races between the IsSet and Set() calls across threads. This second approach keeps the checking code together at the cost of briefly having another task running (unless that is common I would likely take this approach for the code locality).

Winform: Multiple Threads Updating UI at Same Time

I inherited some code that has two non-UI threads that update various WinForm controls.
The code is using InvokeRequired and Invoke to update the UI; however, I still once in a while get the error: Cross-thread operation not valid: Control 'lvReports' accessed on a thread other than it was created on.
I suspect I am dealing with a race condition and that I need to introduce a lock into the method below, but that said, I can find dozens of examples on how to update UI from a non-UI thread safely but no examples or discussion on how to deal with two threads updating the same controls in a race scenario.
So my question is: how do I rewrite the code below to handle updating the UI properly given a race condition and that I need to update UI from non-UI threads?
// two separate theads call this method in a instance of a WinForm
private void LoadReports()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.LoadReports));
}
else
{
// some code removed to keep exampe simple...
SetCtlVisible(lvReports, true);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate { lvReports.Refresh(); });
}
else
{
lvReports.Refresh();
}
}
}
delegate void SetVisibleCallback(Control ctl, bool visible);
private void SetCtlVisible(Control ctl, bool visible)
{
if (ctl.InvokeRequired)
{
SetVisibleCallback d = new SetVisibleCallback(SetCtlVisible);
ctl.Invoke(d, new object[] { ctl, visible });
}
else
{
ctl.Visible = visible;
}
}
Here are some thoughts:
Does this.InvokeRequired differ from ctl.InvokeRequired at any time?
Is the second InvokeRequired test needed given the first?
Is the implementation of SetCtlVisible needed if I keep the first InvokeRequired?
Should I delete the first InvokeRequired and keep all the code in the else clause?
Is lock needed around the else clause?
Using InvokeRequired like this is an anti-pattern. You know that this method is getting called from a thread, InvokeRequired should always be true.
Now you can use it to troubleshoot your problem. If it is false then there's something seriously wrong. Throw an exception, the debugger will stop and let you find out why it isn't working properly. And always call Invoke(), invoke to a little helper method that does the rest of LoadReports().
Also note that you are using it wrong in the rest of your code. You know that the remainder of LoadReports() runs on the UI thread, you used Invoke(). No point in testing it again, including inside SetCtlVisible().
The typical reason for getting the bomb is because the thread is running LoadReports() too soon, before the form's window is created. You need to interlock that. The form's Load event is the signal.

Best way to report thread progress

I have a program that uses threads to perform time-consuming processes sequentially. I want to be able to monitor the progress of each thread similar to the way that the BackgroundWorker.ReportProgress/ProgressChanged model does. I can't use ThreadPool or BackgroundWorker due to other constraints I'm under. What is the best way to allow/expose this functionality. Overload the Thread class and add a property/event? Another more-elegant solution?
Overload the Thread class and add a
property/event?
If by "overload" you actually mean inherit then no. The Thread is sealed so it cannot be inherited which means you will not be able to add any properties or events to it.
Another more-elegant solution?
Create a class that encapsulates the logic that will be executed by the thread. Add a property or event (or both) which can be used to obtain progress information from it.
public class Worker
{
private Thread m_Thread = new Thread(Run);
public event EventHandler<ProgressEventArgs> Progress;
public void Start()
{
m_Thread.Start();
}
private void Run()
{
while (true)
{
// Do some work.
OnProgress(new ProgressEventArgs(...));
// Do some work.
}
}
private void OnProgress(ProgressEventArgs args)
{
// Get a copy of the multicast delegate so that we can do the
// null check and invocation safely. This works because delegates are
// immutable. Remember to create a memory barrier so that a fresh read
// of the delegate occurs everytime. This is done via a simple lock below.
EventHandler<ProgressEventArgs> local;
lock (this)
{
var local = Progress;
}
if (local != null)
{
local(this, args);
}
}
}
Update:
Let me be a little more clear on why a memory barrier is necessary in this situation. The barrier prevents the read from being moved before other instructions. The most likely optimization is not from the CPU, but from the JIT compiler "lifting" the read of Progress outside of the while loop. This movement gives the impression of "stale" reads. Here is a semi-realistic demonstration of the problem.
class Program
{
static event EventHandler Progress;
static void Main(string[] args)
{
var thread = new Thread(
() =>
{
var local = GetEvent();
while (local == null)
{
local = GetEvent();
}
});
thread.Start();
Thread.Sleep(1000);
Progress += (s, a) => { Console.WriteLine("Progress"); };
thread.Join();
Console.WriteLine("Stopped");
Console.ReadLine();
}
static EventHandler GetEvent()
{
//Thread.MemoryBarrier();
var local = Progress;
return local;
}
}
It is imperative that a Release build is ran without the vshost process. Either one will disable the optimization that manifest the bug (I believe this is not reproducable in framework version 1.0 and 1.1 as well due to their more primitive optimizations). The bug is that "Stopped" is never displayed even though it clearly should be. Now, uncomment the call to Thread.MemoryBarrier and notice the change in behavior. Also keep in mind that even the most subtle changes to the structure of this code currently inhibit the compiler's ability to make the optimization in question. One such change would be to actually invoke the delegate. In other words you cannot currently reproduce the stale read problem using the null check followed by an invocation pattern, but there is nothing in the CLI specification (that I am aware of anyway) that prohibits a future hypothetical JIT compiler from reapplying that "lifting" optimization.
I tried this some time ago and it worked for me.
Create a List-like class with locks.
Have your threads add data to an instance of the class you created.
Place a timer in your Form or wherever you want to record the log/progress.
Write code in the Timer.Tick event to read the messages the threads output.
You might also want to check out the Event-based Asynchronous Pattern.
Provide each thread with a callback that returns a status object. You can use the thread's ManagedThreadId to keep track of separate threads, such as using it as a key to a Dictionary<int, object>. You can invoke the callback from numerous places in the thread's processing loop or call it from a timer fired from within the thread.
You can also use the return argument on a callback to signal the thread to pause or halt.
I've used callbacks with great success.

Proper way to clean up a permanent thread in C#

I have an object, a Timeline, that encapsulates a thread. Events can be scheduled on the timeline; the thread will wait until it is time to execute any event, execute it, and go back to sleep (for either (a) the time it takes to get to the next event or (b) indefinitely if there are no more events).
The sleeping is handled with a WaitEventHandle, which is triggered when the list of event is altered (because the sleep delay may need to be adjusted) or when the thread should be stopped (so the thread can terminate gracefully).
The destructor calls Stop(), and I've even implemented IDisposable and Dispose() also calls Stop().
Still, when I use this component in a forms application, my application will never shut down properly when I close the form. For some reason, Stop() is never called, so neither my object's destructor triggers, nor is the Dispose() method called, before .NET decides to wait for all threads to finish.
I suppose the solution would be to explicitly call Dispose() myself on the FormClose event, but since this class is going to be in a library, and it is actually a layer deeper (that is, the application developer will never actually see the Timeline class), this seems very ugly and an extra (unnecessary) gotcha for the application developer. The using() clause, which I would normally use when resource release becomes an issue, doesn't apply as this is going to be a long-lived object.
On the one hand, I can understand that .NET will want to wait for all threads to finish before it does its final round of garbage collection, but in this case that produces a very clumsy situation.
How can I make my thread clean up after itself properly without adding requirements to consumers of my library? Put another way, how can I make .NET notify my object when the application is exiting, but before it will wait for all threads to finish?
EDIT: In response to the people saying that it is ok for the client program to be aware of the thread: I respectfully disagree.
As I said in my original post, the thread is hidden away in another object (an Animator). I instantiate an Animator for another object, and I tell it to perform animations, such as "blink this light for 800ms".
As a consumer of the Animator object, I do not care how the Animator makes sure that the light blinks for exactly 800ms. Does it start a thread? I don't care. Does it create a hidden window and use system timers (ew)? I don't care. Does it hire midgets to turn my light on and off? I don't care.
And I especially don't want to have to care that if I ever create an Animator, I have to keep track of it and call a special method when my program exits, in contrast to every other object. It should be a concern of the library implementor, not the library consumer.
EDIT: The code is actually short enough to show. I'll include it for reference, sans methods that add events to the list:
internal class Timeline : IDisposable {
private Thread eventThread;
private volatile bool active;
private SortedList<DateTime, MethodInvoker> events = new SortedList<DateTime,MethodInvoker>();
private EventWaitHandle wakeup = new EventWaitHandle(false, EventResetMode.AutoReset);
internal Timeline() {
active = true;
eventThread = new Thread(executeEvents);
eventThread.Start();
}
~Timeline() {
Dispose();
}
private DateTime NextEvent {
get {
lock(events)
return events.Keys[0];
}
}
private void executeEvents() {
while (active) {
// Process all events that are due
while (events.Count > 0 && NextEvent <= DateTime.Now) {
lock(events) {
events.Values[0]();
events.RemoveAt(0);
}
}
// Wait for the next event, or until one is scheduled
if (events.Count > 0)
wakeup.WaitOne((int)(NextEvent - DateTime.Now).TotalMilliseconds);
else
wakeup.WaitOne();
}
}
internal void Stop() {
active = false;
wakeup.Set();
}
public void Dispose() {
Stop();
}
}
Maybe set the Thread.IsBackground property to true?
eventThread = new Thread(executeEvents);
eventThread.IsBackground = true;
eventThread.Start();
Another option is to use the Interrupt method to wake it up. Just make sure that you catch the ThreadInterruptedException in the thread that you are interrupting, and that it shuts down when it happens.
active = false;
eventThread.Interrupt();
try { eventThread.Join(); } // Wait for graceful shutdown
catch (Exception) { }
Not quite sure how that EventWaitHandle of yours works though... When I did something similar once, I just used the regular Thread.Sleep =)
I don't think it is unreasonable to require clients to Stop() the thread for shutdown at all. There are ways you can create threads whose continued execution will not stop the application from exiting (although I don't have the details off the top of my head). But expecting to launch and terminate a worker thread is not too much of a burden for the client.
There is no way to get .NET to notify your thread without the clients cooperation. If you're designing your library to have a long running background thread, then the client app has to be designed to know about it.
Application::ApplicationExit is a static event, is it acceptable to listen for it and do your special cleanup work?
Implementing IDisposable should be enough indication that your clients should be using your class in a "using" block.
Implement IDisposable properly, including implementing a finaliser that calls Dispose(true). You Animator object can then do any clean up it wishes to, including stopping the thread if necessary.

Categories