does aborting a thread while in 'using' block dispose used instance - c#

I'm starting a thread like this:
nameOfThread = new Thread(() =>
{
//do stuff
});
nameOfThread.Start();
At some point inside this anonymous function I open a WinSCP session like this:
using (Session session = new Session())
{
//do stuff
}
If I abort the thread (from somewhere else) like this nameOfThread.Abort() while still doing stuff inside using, is the session disposed at the end?

Most likely it will, but you can't be sure.
According to the documentation:
When this method [Abort] is invoked on a thread, the system throws a ThreadAbortException in the thread to abort it.
And we know exceptions will still let using statements dispose, as they should. (Give and take a few exceptions)
On the other hand, if you can end the thread gracefully, for example with a CancellationTokenSource, it would be a lot nicer for your app. It will offer much more control over the actual termination of your thread and the handling of exceptions.

I answered you can guarantee that the using statement will always call Dispose and I stand corrected, I was wrong.
There is a potential race condition with the using statement that doesn't guarantee disposing and I've put together a console app illustrating this (which isn't hard or trivial).
I was correct when showing how the IL generates using like so:
var session = new Session(); //If this causes an error or abort happens during initialization then we don't enter try
//If abort is called here then we never enter try
//In either case above we may have undisposed resources initialized at this point
try
{
//do stuff
}
finally
{
session.Dispose();
}
However; note the comments where I show the race condition that may occur if aborted before entering try.
Here is a console app written just to prove this point. The first works as expected but if you add the commented out code //thread.Abort() when we initialize R then you will see it init but never dispose :/
using System;
using System.Threading;
namespace Question_Answer_Console_App
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start Main");
Thread thread = null;
thread = new Thread(new ThreadStart(() =>
{
Console.WriteLine("Thread Started");
using (var r = new R(thread))
{
Console.WriteLine($"Using {nameof(R)}");
}
}));
thread.Start();
thread.Join();
Console.WriteLine("End Main");
Console.ReadKey();
}
}
public class R : IDisposable
{
public R(Thread thread)
{
Console.WriteLine($"Init {nameof(R)}");
//thread.Abort();
}
public void Dispose()
{
Console.WriteLine($"Disposed {nameof(R)}");
}
}
}
Output with //thread.Abort() commented out:
Start Main
Thread Started
Init R
Using R
Disposed R
End Main
Output with thread.Abort() not commented out:
Start Main
Thread Started
Init R
End Main

Related

Is it OK to have an empty while block when using WaitOne with named mutexes for IPC?

Basically, multiple instances of the same process will do this:
using (var mutex = new System.Threading.Mutex(false, MUTEX_NAME))
{
while (!mutex.WaitOne(100)) { /* wait to acquire mutex from other process */ }
try
{
doSynchronizedWork();
}
finally
{
mutex.ReleaseMutex();
}
}
Will there be any pitfalls? Can a process exit without releasing the mutex? Will an AbandonedMutexException actually be thrown if that happens? Or will another process just acquire the mutex? Something else?
Edit:
Looks like the correct way should be (at least my scenario) would be to do this:
using (var mutex = new System.Threading.Mutex(false, MUTEX_NAME))
{
bool lockObtained = false;
while (!lockObtained)
{
try
{
while (!mutex.WaitOne()) { /* wait to acquire mutex */ }
lockObtained = true;
}
catch (AbandonedMutexException ignored)
{
// mutex abandoned by another
// process before that process completed.
// We can now try to obtain it again.
}
}
try
{
doSynchronizedWork();
}
finally
{
mutex.ReleaseMutex();
}
}
What's the point of this? Simply wait without a timeout.
When a process exits all resources are cleaned up. An AbandonedMutexException must be assumed to be able to happen in IPC scenarios because the other process might fail at any time (due to a bug or out of memory and such).
In case you are doing this so that Thread.Abort works: Thread.Abort is super dangerous. Leave a comment and I'll be able to help you migrate to something better.

Set thread lifetime at startup

Is there a way to set a value for how long a thread should (maximally) be alive when you start the thread?
Said in another way, with "pseudocode", is there anything like this:
Thread t = new Thread();
t.start();
t.abort_after_x_seconds(30);
which would make the thread abort if it lived more than 30 seconds.
Edit: I still can't get it to work, what I originally had is:
while(true)
{
if(...)
{
Thread t = new Thread(new ThreadStart(startMethod));
t.start();
}
Thread.sleep(...);
}
the problem is that sometimes the threads will hang (I'm not implementing what the threads do so I don't know exactly why (it's a school project, we're noobs at organizing)), so I want to kill those threads. I tried using Tasks and CancellationTokens as in the examples below, but when the Task hangs
it can't check if a cancellation request has occured.
Most of the time, you shouldn't be using Threads, use Tasks instead. They are more convenient and more efficient.
Aborting something is not safe, you should use cooperative cancellation instead. If you're calling a method that supports cancellation, then just pass it a cancellation token that will be cancelled after 30 seconds.
So your code could look like this (using .Net 4.5):
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)));
var task = Task.Run(() => YourMethod(cts.Token), cts.Token);
[EDIT: My response was far too slow. But I'll leave this here for the sample code.]
You should use co-operative cancellation for this purpose. The thread itself will need to detect when it should exit, and respond appropriately.
There's a thing called a CancellationToken produced from a CancellationTokenSource that you can use for this purpose.
There's even a CancellationTokenSource constructor which lets you set a timeout.
Here's some sample code to demonstrate its use:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
private void run()
{
using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
{
var task = Task.Run(() => exampleOne(tokenSource.Token));
task.Wait();
}
using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
{
var task = Task.Run(() => exampleTwo(tokenSource.Token));
task.Wait();
}
Console.WriteLine("Done.");
}
static void exampleZero()
{
Console.WriteLine("Starting exampleZero()");
try
{
Thread.Sleep(10000); // Simulate work.
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation cancelled.");
}
Console.WriteLine("Exiting exampleZero()");
}
static void exampleOne(CancellationToken cancellation)
{
Console.WriteLine("Starting exampleOne()");
// Busy loop processing.
while (!cancellation.IsCancellationRequested)
{
// Do some work.
}
Console.WriteLine("Exiting exampleOne()");
}
static void exampleTwo(CancellationToken cancellation)
{
Console.WriteLine("Starting exampleTwo()");
while (!cancellation.WaitHandle.WaitOne(100)) // Wait 100ms between work.
{
// Do some work.
}
Console.WriteLine("Exiting exampleTwo()");
}
static void Main()
{
new Program().run();
}
}
}
As commenters have said, using Abort is bad practice and not guaranteed to abort immediately.
Why would you want to keep the thread alive? The thread will be released back to the pool when the task assigned to it is completed. The next time the task is run on the thread will automatically be given from the pool of threads either by creating another new one or re-using one that is available in the threadpool.
Sounds like your logic/code is bad and needs to be fixed rather than waiting for something for x seconds then terminating it, which in itself will cause knock on problems.
Perhaps you need a timer instead which can tick after 30 seconds then you can disable the timer and kill the task at hand.

Alternating threads #2

Imagine a situation in which there are one king and n number of minions submitted to him. When the king says "One!", one of the minions says "Two!", but only one of them. That is, only the fastest minion speaks while the others must wait for another call of the king.
This is my try:
using System;
using System.Threading;
class Program {
static bool leaderGO = false;
void Leader() {
do {
lock(this) {
//Console.WriteLine("? {0}", leaderGO);
if (leaderGO) Monitor.Wait(this);
Console.WriteLine("> One!");
Thread.Sleep(200);
leaderGO = true;
Monitor.Pulse(this);
}
} while(true);
}
void Follower (char chant) {
do {
lock(this) {
//Console.WriteLine("! {0}", leaderGO);
if (!leaderGO) Monitor.Wait(this);
Console.WriteLine("{0} Two!", chant);
leaderGO = false;
Monitor.Pulse(this);
}
} while(true);
}
static void Main() {
Console.WriteLine("Go!\n");
Program m = new Program();
Thread king = new Thread(() => m.Leader());
Thread minion1 = new Thread(() => m.Follower('#'));
Thread minion2 = new Thread(() => m.Follower('$'));
king.Start();
minion1.Start();
minion2.Start();
Console.ReadKey();
king.Abort();
minion1.Abort();
minion2.Abort();
}
}
The expected output would be this (# and $ representing the two different minions):
> One!
# Two!
> One!
$ Two!
> One!
$ Two!
...
The order in which they'd appear doesn't matter, it'd be random. The problem, however, is that this code, when compiled, produces this instead:
> One!
# Two!
$ Two!
> One!
# Two!
> One!
$ Two!
# Two!
...
That is, more than one minion speaks at the same time. This would cause quite the tumult with even more minions, and a king shouldn't allow a meddling of this kind.
What would be a possible solution?
For future readers, here's the final, working code:
using System;
using System.Threading;
class Program {
static AutoResetEvent leader = new AutoResetEvent(false);
static AutoResetEvent follower = new AutoResetEvent(false);
void Leader() {
do {
Console.WriteLine(" One!");
Thread.Sleep(300);
follower.Set(); // Leader allows a follower speak
leader.WaitOne(); // Leader waits for the follower to finish speaking
} while(true);
}
void Follower (char emblem) {
do {
follower.WaitOne(); // Follower waits for the leader to allow speaking
Console.WriteLine("{0} Two!", emblem);
leader.Set(); // Follower finishes speaking
} while(true);
}
static void Main() {
Console.WriteLine("Go!\n");
Program m = new Program();
Thread king = new Thread(() => m.Leader());
Thread minion1 = new Thread(() => m.Follower('#'));
Thread minion2 = new Thread(() => m.Follower('$'));
Thread minion3 = new Thread(() => m.Follower('&'));
king.Start();
minion1.Start();
minion2.Start();
minion3.Start();
Console.ReadKey();
king.Abort();
minion1.Abort();
minion2.Abort();
minion3.Abort();
}
}
Try using an AutoResetEvent instead of a lock/monitor. It allows you to create a "gate" that only one thread can get through at a time.
Your Follower() threads would call event.WaitOne() (optionally with a timeout). Your Leader() function would call event.Set(), which will release one of the waiting threads.
An AutoResetEvent (as opposed to other types of wait handles) will automatically "close the gate" once of the waiting threads is through.
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
You aren't locking the followers down. So both threads are seeing leaderGo are true, and respond. Have the thread lock itself down before writing out, and that should fix it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Threading
{
class Program
{
static bool leaderGO = false;
static bool followerGo = false;
void Leader()
{
do
{
lock (this)
{
//Console.WriteLine("? {0}", leaderGO);
if (leaderGO) Monitor.Wait(this);
Console.WriteLine("> One!");
Thread.Sleep(200);
leaderGO = true;
followerGo = true;
Monitor.Pulse(this);
}
} while (true);
}
void Follower(char chant)
{
do
{
lock (this)
{
//Console.WriteLine("! {0}", leaderGO);
if (!leaderGO) Monitor.Wait(this);
if(followerGo)
{
followerGo = false;
Console.WriteLine("{0} Two!", chant);
leaderGO = false;
}
Monitor.Pulse(this);
}
} while (true);
}
static void Main()
{
Console.WriteLine("Go!\n");
Program m = new Program();
Thread king = new Thread(() => m.Leader());
Thread minion1 = new Thread(() => m.Follower('#'));
Thread minion2 = new Thread(() => m.Follower('$'));
king.Start();
minion1.Start();
minion2.Start();
Console.ReadKey();
king.Abort();
minion1.Abort();
minion2.Abort();
}
}
}
What you're experiencing is a race condition. You have two separate threads operating on an unlocked resource (leaderGo), which controls their access to the critical section (printing out "Two!").
Placing a mutex lock (as recommended by manman) on leaderGo before printing out "Two!" is a start. You will also need to check to ensure that the value of leaderGo is still true before printing it, as both threads will eventually acquire the lock, but only one of them will acquire the lock while leaderGo is true.
Something like:
lock(leaderGo)
{
if (leaderGo)
Console.WriteLine("{0} Two!", chant);
leaderGo = false;
}
This will ensure only one follower is capable of responding (since it requires the lock). It will not guarantee which thread obtains the lock, the frequency at which specific threads obtain the lock, or anything like that. However, in each pass every thread will obtain the lock -- all that matters is who was first.
A few tips:
NEVER use lock(this). By locking the object from the inside, anything that uses your object as a locking focus will interfere with your own code's ability to synchronize.
NEVER use Thread.Abort(). It is evil; it kills your running threads by injecting an exception, which is unpredictable and thus difficult or impossible to catch and handle gracefully. Instead, try passing an instance of a class with a boolean property IsCancelled, and use !IsCancelled as the condition under which you keep looping.
The actual problem with your code is that your combination of Monitor and locks is causing the lock to be released from within the critical section by the thread that acquires the lock, if that thread thinks someone else must go first. You have three threads, each of which can acquire, then release and wait, before reacquiring the lock and proceeding as if the condition under which it waited was now false.
One possible scenario:
Follower 1 enters the critical section (lock() block) of Follower.
Follower 2 approaches the critical section of Follower and is told to wait.
King approaches the critical section of Leader and is told to wait.
Follower 1 sees that leaderGO is false and waits, releasing the lock on the critical section.
King, despite being second in line, "races" into the critical section ahead of Follower 2.
King continues (leaderGo is false so King never Wait()s), calls "One!" and sets the flag before releasing the lock at the end of the critical section.
Follower 2 now "races" into the critical section ahead of Follower 1, sees the flag is set, and continues, calling "Two!" and exiting the critical section.
Follower 1 now gets a turn, reacquiring the lock in the middle of its critical section. It no longer cares that leaderGo is false; it's past that check already. So, it continues, also calls "Two!", sets the flag (to the value it had already been) and exits.
There are many possible ways that these threads could "race" based on the way you have it set up.
Here's something that may work a little better; it's called double-checked locking, and while it isn't foolproof it's much better than what you have:
private static readonly object syncObj = new object();
void Leader() {
do {
if(leaderGo)
{
Thread.Sleep(200);
continue;
}
lock(syncObj) {
//the "double-check"; here it's not necessary because there's
//only one King to set leaderGo to true,
//but it doesn't hurt anything.
if(leaderGo) continue;
//we won't get here unless we have control of
//the critical section AND must do something.
Console.WriteLine("> One!");
Thread.Sleep(200);
leaderGO = true;
}
} while(true);
}
void Follower (char chant) {
do {
if(!leaderGo)
{
Thread.Yield();
continue;
}
lock(syncObj) {
//this double-check is critical;
//if we were waiting on the other follower to release
//the lock, they have already shouted out and we must not do so.
if (!leaderGO) continue;
//we only get here if we have
//control of the lock and should shout out
Console.WriteLine("{0} Two!", chant);
leaderGO = false;
}
} while(true);
}
EDIT: As mentioned in the comments, this model doesn't rely on luck, but it isn't foolproof because .NET, for performance, can allow several copies of leaderGO to exist in the caches of various threads, and synchronize them behind the scenes. If .NET isn't johnny-on-the-spot with that synchronization, the double-check performed by one thread may see the old, "stale" state of the flag and incorrectly move on when it should instead get out.
You can fix this one of two simple ways:
Put a MemoryBarrier just after any update of leaderGO, and just before any read of leaderGO. Memory barriers, or "memory fences" as they can be called in other languages, basically blocks each running thread at the memory barrier, until all threads are at a memory barrier (or blocked in other ways), ensuring that all instructions occurring before the memory barrier have been executed before any instructions after it are run.
Declare leaderGO as volatile. A volatile variable cannot be optimized by .NET; it is guaranteed to be in exactly one location in memory that is accessible, however inefficiently, by any thread that would run that code. Therefore any update to its value is immediately seen by any other thread.

Object synchronization method was called from an unsynchronized block of code. Exception on Mutex.Release()

I have found different articles about this exception but none of them was my case.
Here is the source code:
class Program
{
private static Mutex mutex;
private static bool mutexIsLocked = false;
static void Main(string[] args)
{
ICrmService crmService =
new ArmenianSoftware.Crm.Common.CrmServiceWrapper(GetCrmService("Armsoft", "crmserver"));
//Lock mutex for concurrent access to workflow
mutex = new Mutex(true, "ArmenianSoftware.Crm.Common.FilterCtiCallLogActivity");
mutexIsLocked = true;
//Create object for updating filtered cti call log
ArmenianSoftware.Crm.Common.FilterCtiCallLog filterCtiCallLog =
new ArmenianSoftware.Crm.Common.FilterCtiCallLog(crmService);
//Bind events
filterCtiCallLog.CtiCallsRetrieved += new EventHandler<ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs>(filterCtiCallLog_CtiCallsRetrieved);
//Execute filter
try
{
filterCtiCallLog.CreateFilteredCtiCallLogSync();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (mutexIsLocked)
{
mutexIsLocked = false;
mutex.ReleaseMutex();
}
}
}
static void filterCtiCallLog_CtiCallsRetrieved(object sender,
ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs e)
{
tryasasas
{
if (mutexIsLocked)
{
mutexIsLocked = false;
mutex.ReleaseMutex();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
filterCtiCallLog.CreateFilteredCtiCallLogSync(); function executes requests to server, and raises some events, one of which is CtiCallsRetrieve event. And I need to release the mutex when this event is fired. But on calling the mutex.Release() function exception is thrown. CreateFilteredCtiCallLogSync works synchronously. What is the problem?
Keeping a bool around that indicates that the mutex is owned is a grave mistake. You are not making the bool thread-safe. You got into this pickle because you are using the wrong synchronization object. A mutex has thread-affinity, the owner of a mutex is a thread. The thread that acquired it must also be the one that calls ReleaseMutex(). Which is why your code bombs.
You in all likelihood need an event here, use AutoResetEvent. Create it in the main thread, call Set() in the worker, WaitOne() in the main thread to wait for the worker to complete its job. And dispose it afterwards. Also note that using a thread to perform a job and having your main thread wait for its completion is not productive. You might as well have the main thread do the job.
If you are actually doing this to protect access to an object that's not thread-safe (it isn't clear) then use the lock statement.
Another reason why this exception may occur:
if (Monitor.TryEnter(_lock))
{
try
{
... await MyMethodAsync(); ...
}
finally
{
Monitor.Exit(_lock);
}
}
I get this exception on Monitor.Exit when after 'await' another thread continues execution.
Edit:
Use SemaphoreSlim, because it doesn't require releasing thread to be the same.
You will also run into this exception if you do the following:
mutex.WaitOne();
… Some Work...
await someTask;
mutex.ReleaseMutex();
That's because the code after the await can be executed on a different thread from the line just before. Basically, it seems that if you asynch code now (in early 2020), Mutexes simply don't work. Use events or something.
I have found the problem. First several things about the filterCtiCallLog class. I have designed it so to work both asynchronous and synchronous. For first I have written code for asynchronous execution. I needed a way to trigger events from child worker thread to parent, to report the working state. For this I have used AsyncOperation class and it's post method. Here is the code part for triggering CtiCallsRetrieved event.
public class FilterCtiCallLog
{
private int RequestCount = 0;
private AsyncOperation createCallsAsync = null;
private SendOrPostCallback ctiCallsRetrievedPost;
public void CreateFilteredCtiCallLogSync()
{
createCallsAsync = AsyncOperationManager.CreateOperation(null);
ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost);
CreateFilteredCtiCallLog();
}
private void CreateFilteredCtiCallLog()
{
int count=0;
//do the job
//............
//...........
//Raise the event
createCallsAsync.Post(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count));
//...........
//...........
}
public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved;
private void CtiCallsRetrievedPost(object state)
{
CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs;
if (CtiCallsRetrieved != null)
CtiCallsRetrieved(this, args);
}
}
As you can see the code is executing synchronously. The problem here is in AsyncOperation.Post() method. I presumed that if it is called in the main thread it will act as simply triggering the event, not posting it to parent thread. However it wasn't the case. I don't know how it is working, but I have changed the code, to check if the CreateFilteredCtiCallLog is called sync or async. And if it is async call I used AsyncOperation.Post method, if not, I have simply triggered the EventHandler if it is not null. Here is the corrected code
public class FilterCtiCallLog
{
private int RequestCount = 0;
private AsyncOperation createCallsAsync = null;
private SendOrPostCallback ctiCallsRetrievedPost;
public void CreateFilteredCtiCallLogSync()
{
createCallsAsync = AsyncOperationManager.CreateOperation(null);
ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost);
CreateFilteredCtiCallLog(false);
}
private void CreateFilteredCtiCallLog(bool isAsync)
{
int count=0;
//do the job
//............
//...........
//Raise the event
RaiseEvent(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count),isAsync);
//...........
//...........
}
public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved;
private void RaiseEvent(SendOrPostCallback callback, object state, bool isAsync)
{
if (isAsync)
createCallsAsync.Post(callback, state);
else
callback(state);
}
private void CtiCallsRetrievedPost(object state)
{
CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs;
if (CtiCallsRetrieved != null)
CtiCallsRetrieved(this, args);
}
}
Thanks everybody for the answers!
I have seen this happen when you lock code using a Monitor, then call an async code and you get this, when using a lock(object) you get a compiler error, however between monitor.enter(object) and Monitor.Exist(object) the compiler does not complain... unfortunately.
Using a flag to attempt to monitor a kernel synchro object state will just not work - the point of using those synchro calls is that they work correctly without any explicit checking. Setting flags will just cause intermittent problems because the flag may be changed inappropriately due to interrupts between checking the flag and acting on it.
A mutex can only be released by the threat that acquired it. If you callback is called by a different thread, (one internal to CreateFilteredCtiCallLogSync() or a kernel thread pool), the release will fail.
It's not clear exactly what you are attempting to do. Presumably, you want to serialize access to CreateFilteredCtiCallLogSync() and the callback flags that the instance is available for re-use? If so, you could use a semaphore instead - init. it to one unit, wait for it at the start and release it in the callback.
Is there some issue where sometimes the callback is not called, and hence the try/finally/release? If so this way out seems a bit dodgy if the callback is asychronous and may be called by another thread after the setup thread has left the function.
I only had this one once or twice, and in every case it came about by trying to release a mutex I didn't own.
Are you sure the events are raised on the same thread the mutex was acquired on?
Although you mention that filterCtiCallLog.CreateFilteredCtiCallLogSync() is a blocking call, perhaps it spawns of worker threads that raise the event?
Maybe not the most meaningful error message, I've seen this happen in some third party code as below,
object obj = new object();
lock (obj)
{
//do something
Monitor.Exit(obj);//obj released
}//exception happens here, when trying to release obj
I have read the thread and got some ideas. But did not know what exactly need to do to solve the issue. I face the same error when uploading the image to the s3 at nopCommerce solution.And the below code is working for me.
using var mutex = new Mutex(false, thumbFileName);
mutex.WaitOne();
try
{
if (pictureBinary != null)
{
try
{
using var image = SKBitmap.Decode(pictureBinary);
var format = GetImageFormatByMimeType(picture.MimeType);
pictureBinary = ImageResize(image, format, targetSize);
}
catch
{
}
}
if (s3Enabled)
//await S3UploadImageOnThumbsAsync(thumbFileName, pictureBinary, picture.MimeType, picture, targetSize);
// The above code was causing the issue. Because it is wait for the thread.
//So I replace the code below line and the error disappear. This also kind of same implementation by nopCommerce.
//The thread need to wait.
S3UploadImageOnThumbsAsync(thumbFileName, pictureBinary, picture.MimeType, picture, targetSize).Wait();
else
File.WriteAllBytes(thumbFilePath, pictureBinary);
}
finally
{
mutex.ReleaseMutex();
}

Does a thread close automatically?

Im using a gmail class so that my app can send me notification over gmail.
Its done like this:
public static void SendMessage(string message)
{
Notification.message = message;
Thread t = new Thread(new ThreadStart(SendMessageThreaded));
t.Start();
}
and the threaded function look like this:
private static void SendMessageThreaded()
{
try
{
if (Notification.message != "")
RC.Gmail.GmailMessage.SendFromGmail("accname", "accpass", "email", "subject", Notification.message);
Notification.message = "";
}
catch
{ }
}
So after SendMessageThreaded is run, does it close by itself or do i have to
t.Start()
t.Abort()
or something?
The thread needs to be started once - at which point it will execute the code block assigned to it and exit.
You don't need to explicitly clean up the thread in most cases (unless you want to bail out early for example )
Yes , the thread is closed by itself.
That is when all instructions in the method run on the secodn thread have been called.
yes,definitely. it will close itself when it ends.
The thread will go out of scope and be available for garbage collection as soon as SendFromGmail finishes.
So yes, it closes automatically.
No need, it will return back to the thread pool and wait for other task, if none it will kill itself.
Yes it will close, but you should but a timeout in order to avoid zombies anyway if the main thread crash while the second thread is waiting for it.
The Abort() method throws an ThreadAbortException that you can handle:
public void SendMessageThreaded()
{
try
{
// thread logic
}
catch (ThreadAbortException tae)
{
// thread was aborted, by t.Abort()
}
catch (Exception ex)
{
// other error
}
}
By using
t.Abort(myObject)
you can "send" any object that helps you to handle the abort handling. You can use ExceptionState property to access that object.

Categories