c# CF Restart a thread - c#

Supose you have a form with a button that starts/stops a thread (NOT pausing or interrupting, I really need to stop the thread !)
Check out this code:
Constructor()
{
m_TestThread = new Thread(new ThreadStart(ButtonsThread));
m_bStopThread = false;
}
ButtonClick
{
// If the thread is not running, start it
m_TestThread.Start();
// If the thread is running, stop it
m_bStopThread = true;
m_TestThread.Join();
}
ThreadFunction()
{
while(!m_bStopThread)
{
// Do work
}
}
2 questions (remember CF):
- How can I know if the thread is running (I cannot seem to access the m_pThreadState, and I've tried the C++ GetThreadExitCode(), it give false results) ?
- Most important question : if I have stopped the thread, I cannot restart it, most probably because the m_TestThread.m_fStarted is still set (and it is private so I cannot access it) ! And thus m_TestThread.Start() generates an exception (StateException).
Stopping the thread with an Abort() doesn't solve it. If I put my m_TestThread = null; it works, but then I create a memory leak. The GC doesn't clean up either, even if I wait for xx seconds.
Anybody has an idea ? All help highly appreciated !
Grtz
E

You can use Thread.Suspend and Thread.Resume for stopping/restarting the thread.
For checking the thread's status you can use Thread.ThreadState.

Related

Shutting down a foreground thread on application quit?

I am trying to figure out a way to shutdown my foreground thread in the event that my application quits/terminates/etc..
From what I have tested and read about, it is to my understanding that the main thread is always last to execute. Is this always true?
If so, then could someone suggest of a way to graciously signal a shutdown of a foreground thread? (in the event of application quit) Or is this even possible?
I am kinda getting a feeling that a foreground thread should be responsible of shutting down itself (not relying on a outside signal), unless it is known that the process will not terminate/shutdown prematurely. Is this also true?
I have a couple of reasons for using a foreground thread instead of a background thread:
My thread allocates [ThreadStatic]native memory using Marshal.AllocHGlobal, and it needs to be properly released.
It is a server application and preferably it would send all the queued packets before shutting down (not essential).
For example:
volatile bool running = true;
static void Main()
{
AppDomain.CurrentDomain.ProcessExit += new
EventHandler(OnProcessExit);
var t = new Thread(ReadWrite);
t.Start();
ConsoleKeyInfo cki;
Console.WriteLine("Running..\n");
bool stopped = false;
while(!stopped)
{
// do server stuff..
.......
if (Console.KeyAvailable)
{
cki = Console.ReadKey(true);
if (cki.Key == ConsoleKey.X)
{
stopped = true;
}
}
}
}
private void ReadWrite()
{
while (running)
{
// do stuff....
....
Thread.Sleep(15);
}
FreeMemory();
}
public void EndServer()
{
FreeMemory();
running = false;
// do other stuff...
}
private void OnProcessExit(object sender, EventArgs e)
{
EndServer();
}
This results in:
stopped is made true
OnProcessExit is not called. (I have also tried explicitly calling EndServer() but got the same result
application hangs
So I suspect (but I am not sure) that since the main thread is last to execute, the program is waiting for ReadWrite to finish, which means what I am doing is not possible?
If it is not possible, I will either: Look to see if it is possible to do with background thread, or I will look into redesigning my native memory implementation.
It turns out I had no idea that native memory is freed when program is closed. Putting my thread in background will solve the rest of my issues.
Edit for future reference:
A background thread did not solve point 2, though it was not essential for me so I went ahead with this solution anyways.

How to close a worker thread early

I have multiple worker threads, in which each worker downloads an audio file. When the user closes the form in which these audio files get downloaded I want all of these worker threads to stop running.
I'm using a library that does the downloading of the audio files for me. So all I have to do in order to start downloading is audioDownloader.Execute();. This means I'm not using a while loop which I've seen used on msdb to end threads early.
I've tried aborting the threads on DownloadForm_FormClosing but when I try to reopen the download form, the audio files won't start downloading anymore. I've also tried using thread.Join() but the form just freezes... This is the code I use:
//DownloadForm.cs
private void DownloadForm_FormClosing(object sender, FormClosingEventArgs e)
{
isdownloadformclosing = true;
//each AudioFile holds a thread
foreach(AudioFile v in AudioFiles)
{
v.thread.Abort();
v.thread = null;
}
}
//AudioFile.cs
try
{
AudioDownloader.Execute();
}
catch(Exception e)
{
if(!DownloadForm.isdownloadformclosing)
DownloadForm.ShowErrorForId(this.Id, e);
}
..when I try to reopen the download form, the audio files won't start downloading anymore
you can't restart the **Abort**ed thread
Once the thread terminates, it cannot be restarted with another call to Start.
Thread.Start Method
What you can do for your "reopen", for example:
protected Thread tDownloader;
...
if(tDownloader == null || tDownloader.ThreadState == ThreadState.Unstarted || tDownloader.ThreadState == ThreadState.Stopped)
{
tDownloader = new System.Threading.Thread(() => {
...TODO...
});
....
tDownloader.Start();
}
see ThreadState Enumeration for more detail
Thread.Abort - raises a ThreadAbortException in the thread on which it is invoked, to begin the process of terminating the thread
After call, ThreadState has Aborted status, but its state has not yet changed to Stopped.
We can't really tell much without seeing the code for this AudioDownloader or AudioFile classes... either AudioDownloader should have a cancel method which (internally) deals with everything it needs to, or you need to check what's happening in AudioFile to cause the problem.
I suspect that if it's not expecting it's 'thread' object to be set to null, when you try to reuse the object it doesn't like it because it no longer has a thread... try recreating the AudioDownloader object each time your form loads - that should let it start as if it was starting from stratch again.
Like I say, without more code, not much we can do!

How to kill Thread in my C# application?

I want to kill/destroy the thread in my application on Button Click event.
private void stop_btn_Click(object sender, EventArgs e)
{
Thread.Sleep();
}
Does this event hang up my application?
That's the code where from my thread starts
DataTable myTable = new DataTable();`enter code here`
myTable = msgDataSet.Tables["text"];
DataRow[] myRow;
myRow = myTable.Select();
for (int x = 0; x < myRow.Count(); x++ )
{
SendKeys.SendWait(myRow[x]["msg"].ToString());
SendKeys.SendWait("{Enter}");
int sleep = int.Parse(textBox2.Text);
Thread.Sleep(sleep);
}
Thread Spam1 = new Thread(new ThreadStart(Send1));
Spam1.Start();
See this article for why you should never try to call Thread.Abort:
http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation
The problem is that you break your exception safety within that thread. This is because Thread.Abort will throw an exception within that thread at some arbitrary point, which might be right after a resource is loaded, but before the thread enters a try/catch that would support clean unloading of that resource.
Instead you should build co-operative cancellation into the code you run in that thread. Then set some sort of "cancellation requested" state, and let the thread kill itself. E.g.:
foreach(var value in aBunchOfData)
{
if(isCancelled)
{
break;
}
// Continue processing here...
}
In this case you'd expose isCancelled, and have your parent thread set it to true.
This pattern is made clear if you use a BackgroundWorker to implement your background thread.
If you want to forcefully shut down a thread, you can call Abort() which will raise a ThreadAbortedException on the target thread
myThread.Abort()
The target thread has a chance to catch it and clean up any resources if needed (of course, it can also ignore it if it wants to by just catching the exception and moving on, but that is IMO bad practice)
The code you wrote will put UI thread to sleep->your application will hang. How do you implement threading? If you are using BackgroundWorker- you can enable thread cancellation, if you are using Task- you can provide cancel token to it. If you are using Thread- you can choose Abort() method.
PS..If you want to stop your application(main thread)-you can:
close main window || call application exit || call process kill....

Compact Framework 2.0: How can I stop a thread when an object is dispose?

I have this code:
Thread t = new Thread(() => UpdateImage(origin));
t.Name = "UpdateImageThread";
t.Start();
This code is created on a Custom Control. I want to stop this thread (if it's running) when the object is going to be dispose.
This custom control has the following method:
void IDisposable.Dispose()
{
/* My own code */
base.Dispose(true);
}
I think this is the place to put the code but:
How can I know is the thread is running?
How can I take a referece for the thread and stop it?
By the way, UpdateImage call a web service, so I think that it's waiting all of its life.
How can I finish this wait?
Thank you!
It depends a lot on what UpdateImage() does and how well it copes with the Image being disposed while it it still active. If UpdateImage() is your code and contains a loop you can tell it to stop (using a field like _stopping). If not, the best thing may be to do nothing - in the rare case of Disposing the control while the image is still updating you take the penalty of leaving it to the GC.
About how to get the Thread: By saving the reference when and where you create it, for instance int the private member _updateThread.
Now actually stopping (aborting) the thread is a (very) bad idea.
So you'll need an indicator, like
private bool _stopping = false;
And it is up to the UpdateImage() method to react to _stopping == true and stop with what it is doing.
Your Dispose() can then use
_stopping = true;
_updateThread.Join()
Save your thread variable 't' so that you can re-use it later.
Within your Dispose method you want something like:
void IDisposable.Dispose()
{
if(t.IsRunning)
{
cancelThreads = true; // Set some cancel signal that the thread should check to determine the end
t.Join(500); // wait for the thread to tidy itself up
t.Abort(); // abort the thread if its not finished
}
base.Dispose(true);
}
You should be careful aborting threads though, ensure that you place critical section of code within regions that won't allow the thread to stop before it has finished, and catch ThreadAbortExceptions to tidy anything up if it is aborted.
You can do something like this in the threads start method
public void DoWork()
{
try
{
while(!cancelThreads)
{
// Do general work
Thread.BeginCriticalRegion();
// Do Important Work
Thread.EndCriticalRegion();
}
}
catch(ThreadAbortException)
{
// Tidy any nastiness that occured killing thread early
}
}
I suggest to override the Dispose method in your Custom Control.
There you have the reference of your thread and you can call .Join() for example...

How to handle starting/stopping API interface that may take a long time to start

I have an application that needs to work with a vendor-supplied API to do Screen Pops when a call is routed to the user's extension. Another developer worked on getting the API to work and delivered a prototype wrapper class that isn't quite right, and I'm trying to get it right.
Because this API can block for several minutes before returning, the developer started the API interface code in a separate thread, like this:
// constructor
public ScreenPop( ...params... )
{
...
t = new Thread( StartInBackground );
t.Start();
)
private void StartInBackground()
{
_listener = new ScreenPopTelephoneListener();
_bAllocated = true;
_listener.Initialize( _address );
_bInitialized = true;
_listener.StartListening( _extension );
_bListening = true;
}
The call to Initialize is the one that could hang, if the phone server was unresponsive.
I don't think it was intentional on the part of the developer who did this, but when the API is initialized this way, the thread keeps running, so that now I have to stop the thread before I can clean up when I want to. I also have to use Invoke to get events from the thread, as others so kindly pointed out in my previous question, but that is working now.
Anyway, here is the logic used to shut everything down and clean up:
public void ShutdownFunc()
{
try
{
if ( _bListening )
{
_listener.StopListening();
_bListening = false;
}
if ( _bInitialized )
{
_listener.Shutdown();
_bInitialized = false;
}
if ( _bAllocated )
{
_listener = null;
_bAllocated = false;
}
}
}
Of course, there is a try/catch around the whole mess to prevent unhandled exceptions.
My biggest problem is, how do I call the shutdown code when the API interface code is running in a separate thread? I need to clean up in case the user logs off and then logs back on again, as the API gets confused if I don't. Thread.Abort won't work, as it's not in a place to catch the exception, and the "volatile bool" method won't work either, for obvious reasons (most of the time, the API thread is not active).
So there seems to be no way to call the shutdown logic if the API interface code is running on a separate thread. Thread.Abort() bypasses all the logic and kills the thread without cleaning up. Calling the shutdown logic from the GUI thread hangs when it calls the Shutdown method. So, what can I do?
The IDispose interface just adds another layer of abstraction in the GUI thread, and does nothing to solve the problem here.
For now, to get the rest of the code developed, I am eliminating threads completely. But, before I release the app, I need to figure this out.
Anybody?
Thanks,
Dave
You may further encapsulate initialization logic and check on a ManualResetEvent in the main initialization thread while spawning a worker thread to do the actual initialization. If the ManualResetEvent is set from your main thread while you're still initializing, you can abort the thread doing the actual initialization and do your cleanup, otherwise if the worker thread completes you just stop waiting on the ManualResetEvent.
It's kind of dirty and tricky, but should do what it's supposed to ;)
First of all, if you need to shut down your application and Initialize() is still running, you have only two options:
Wait for 'Initialize' to finish
Abort the thread that's running 'Initialize'.
Aborting the thread should always be the last option, but in case you really need to stop the application and the Initialize doesn't have a timeout parameter, there's no other way.
Also, I would suggest wrapping that 3rd party API in your own class, implementing IDisposable on it and holding the API state using some enum instead of separate bool flags like you did in ShutdownFunc. Add some simple automation machine logic into it to handle each state. And keep the possible states count to minimum needed.
Or maybe throwing that vendor's library in the garbage can ;)
I reworked the logic for the shutdown function, to get rid of the handful of booleans floating around. Here's what the new code looks like:
private enum ApiState { Unallocated, Allocated, Initialized, Listening };
private ApiState _apiState = ApiState.Unallocated;
private void StartInBackground()
{
_listener = new ScreenPopTelephoneListener();
_apiState = ApiState.Allocated;
_phoneListener.Initialize( _strAddress );
_apiState = ApiState.Initialized;
_phoneListener.StartListening( _intExtension.ToString() );
_apiState = ApiState.Listening;
}
public void ShutdownFunc
{
try
{
if ( ApiState.Listening == _apiState )
{
_listener.StopListening();
_listener.Shutdown();
}
if ( ApiState.Initialized == _apiState )
{
_listener.Shutdown();
}
}
catch {}
finally
{
_listener = null;
_apiState = ApiState.Unallocated;
}
}
The problem remains, however, where I can't call the Shutdown logic without hanging the GUI thread. Is there any way to interrupt the worker thread using a call from the GUI thread, short of Abort? Can I possibly set up an event handler and use a manually generated event from the GUI thread to stop the worker thread? Has anyone tried this?
I haven't tried the suggestions regarding starting a new thread for the Initialization call, as that only solves part of the problem and may be unnecessary once I get the real problem resolved.
OK, here goes another attempt. I tried to declare an event and raise that event on the thread, to run the shutdown logic from the thread the API is running on. No luck, it still tries to run the shutdown logic on the GUI thread and hangs the application.
Here's the applicable code:
public delegate void HiPathScreenPop_ShutdownEventHandler( object parent );
class HiPathScreenPop
{
// Shutdown event, raised to terminate API running in separate thread
public event HiPathScreenPop_ShutdownEventHandler Shutdown;
private Thread _th;
//ctor
public HiPathScreenPop()
{
...
_th = new Thread( StartInBackground );
_th.Start();
}
private void StartInBackground()
{
_phoneListener = new ScreenPopTelephoneListener();
_apiState = ApiState.Allocated;
_phoneListener.StatusChanged += new _IScreenPopTelephoneListenerEvents_StatusChangedEventHandler( StatusChangedEvent );
_phoneListener.ScreenPop += new _IScreenPopTelephoneListenerEvents_ScreenPopEventHandler( ScreenPopEvent );
this.Shutdown += new HiPathScreenPop_ShutdownEventHandler( HiPathScreenPop_Shutdown );
_phoneListener.Initialize( _strAddress );
_apiState = ApiState.Initialized;
_phoneListener.StartListening( _intExtension.ToString() );
_apiState = ApiState.Listening;
}
public void KillListener()
{
OnShutdown();
}
private void OnShutdown()
{
if ( this.Shutdown != null )
{
this.Shutdown( this );
}
}
void HiPathScreenPop_Shutdown( object parent )
{
// code from previous posts
}
}
What seems to happen when I call KillListener is this:
1) OnShutdown() gets called on the UI thread (OK)
2) Shutdown( this ) gets called (here's where I expect an event to be raised ont the background thread
3) HiPathScreenPop_Shutdown() gets called on the UI thread, and hangs on the _phoneListener.ShutDown() call, same as if I was not using the event mechanism.
OK, so what piece(s) of magic am I missing, or completely misunderstanding? It seems all the plumbing I created did nothing much except clutter up the code...
Thanks for any reponses,
Dave
When you call an event handler directly from Thread A, all the handlers for that event are also executed on Thread A. There is no way to inject that handler into your other thread. You could spawn another thread to run Shutdown, but this still doesn't solve the problem of Initialize not being finished yet - it just moves the problem yet again. It does let you display a waiting dialog for the user.
Ultimately if this line of code hangs for a while:
_phoneListener.Initialize( _strAddress );
then there's nothing you can really do apart from wait for that to finish (either on the UI thread or in another thread with some form of waiting UI) and have a check after that call that causes the handler thread to exit.
_phoneListener.Initialize( _strAddress );
if (_exit.WaitOne(0))
{
return;
}
In your main shutdown routine you want something like:
_exit.Set();
_th.Join();
// Rest of cleanup code
This will then wait for the thread to exit. I wouldn't recommend calling Abort on a thread ever, as you have no idea what will happen to any state that thread was referencing. If you have to Abort a thread then plan on restarting the whole application to be safe.
With the help of a fellow developer here, I was able to get the code working as desired. What I needed to do was take everything out of the thread except the call to Initialize(), so that the API instance was not running on a separate thread. I then had a different problem, as the status was set from 2 different threads and was not what I expected it to be when I went to clean up.
Here is the final solution:
// declare a background worker to init the API
private BackgroundWorker _bgWorker;
// ctor
public HiPathScreenPop( ... )
{
...
_phoneListener = new ScreenPopTelephoneListener();
_apiState = ApiState.Allocated;
_phoneListener.StatusChanged += new _IScreenPopTelephoneListenerEvents_StatusChangedEventHandler( StatusChangedEvent );
_phoneListener.ScreenPop += new _IScreenPopTelephoneListenerEvents_ScreenPopEventHandler( ScreenPopEvent );
_bgWorker = new BackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(StartInBackground);
_bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler( bgWorker_RunWorkerCompleted );
_bgWorker.RunWorkerAsync();
}
void _bgWorker_DoWork( object sender, DoWorkEventArgs e )
{
_phoneListener.Initialize( _strAddress );
}
void bgWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e )
{
_apiState = ApiState.Initialized; // probably not necessary...
_phoneListener.StartListening( _intExtension.ToString() );
_apiState = ApiState.Listening;
}
Now, the API instance is running in the same thread as the UI and everybody's happy. The call to Shutdwn() no longer hangs, I don't need Invoke() for the callbacks, and the long-running code executes in a background worker thread.
What this code does not show are the great ideas presented earlier for how to handle the case where the user shuts down before the call to Initialize() returns. The final code will be a synthesis of these solutions.
Thanks to all for the great feedback!
Dave

Categories