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.
Related
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
We have implemented a queue for uploading files to box.net.
All files are uploaded successfully. but,I am getting the following exception 1 or 2 times in a week. I couldn't found any cause for this exception.
Exception-Message:
Thread was being aborted.
Exception-Source:
mscorlib
Exception-StackTrace:
at System.Threading.Monitor.ObjWait(Boolean exitContext, Int32 millisecondsTimeout, Object obj)
at System.Threading.Monitor.Wait(Object obj, Int32 millisecondsTimeout, Boolean exitContext)
at System.Threading.Monitor.Wait(Object obj)
at Box.netAPIWebApp.Service.BoxService.monitorOnUploadQueue() in C:\Project\BackupProjects\BoxNetFileUpload\Box.netAPIWebApp\Source\Service\BoxService.cs:line 90
Can any one help on this?
private static readonly BoxService instance = new BoxService();
private Queue<FileCabinetUploadHistory> uploadQueue = new Queue<FileCabinetUploadHistory>();
private BoxService()
{
Thread monitorThread = new Thread(new ThreadStart(monitorOnUploadQueue));
monitorThread.Start();
}
private FileCabinetUploadHistory RemoveFromUploadQueue()
{
lock (uploadQueue)
{
return uploadQueue.Dequeue();
}
}
private void monitorOnUploadQueue()
{
FileCabinetUploadHistory fileCabinetUploadHistory = null;
try
{
while (true)
{
if (uploadQueue.Count < 1)
{
lock (uploadQueue)
{
Monitor.Wait(uploadQueue);
}
}
fileCabinetUploadHistory = uploadQueue.Peek();
if (fileCabinetUploadHistory != null)
{
StartFileUpload(fileCabinetUploadHistory);
}
}
}
catch (Exception exception)
{
log.Error("Error:--> Class name: BoxService, Method name: monitorOnUploadQueue() \n", exception);
}
}
public void AddToUploadQueue(FileCabinetUploadHistory fileCabinetUploadHistory)
{
lock (uploadQueue)
{
if (!uploadQueue.Contains(fileCabinetUploadHistory))
{
uploadQueue.Enqueue(fileCabinetUploadHistory);
Monitor.Pulse(uploadQueue);
}
}
}
Basically a ThreadAbortException means exactly that: Your thread received an external signal to kill itself. Now ThreadAbortException is a bit special because it can not be handled. It just keeps on terminating your thread by rethrowing itself every time you catch it. See http://ericlippert.com/2009/03/06/locks-and-exceptions-do-not-mix/ for details.
So now you probably ask yourself who sent the external signal mentioned above. I don't know. The code you showed does not suffice to say. But there is a very good chance that someone still has a handle of the monitorThread and calls thread.Abort() on it. Does your codebase contain .Abort()? If so rest assured that it's a very bad idea. Again see the above link for details.
If you absolutely have to terminate a thread that is waiting on a monitor there are better ways. For example make the thread wait on multiple monitors at the same time: One for the queue and one to signal for termination. Then instead of killing the thread by abort you just pulse the termination monitor and let the thread shut itself down.
By the way, you are accessing your queue in an unsafe way. Write access seems to be under lock condition but read access (Count, Peek) is not. This is not the way locking is supposed to be used and bad things can (and eventually will) happen. Don't do it! See http://blog.coverity.com/2014/03/12/can-skip-lock-reading-integer/ to find out why.
I got it.
ThreadAbortException occurs when Application pool recycles after every 29 hours.
I have a windows service that sends email in a one of 5 threads (done to increase the speed the service can send email):
private AutoResetEvent block;
private ThreadedQueue<Message> messageQueue;
private void DoSend()
{
try
{
while(!this.disposing)
{
this.block.WaitOne();
Message message = null;
if (this.messageQueue.TryDequeue(out message))
{
this.block.Set();
}
if(message != null)
{
this.Send(message);
}
}
}
catch(Exception ex)
{
// Log
}
}
I have a Queue method that adds one or more new message to the messageQueue and calls block.Set() so that one of the 5 threads can send the message. When one of the threads is allowed to run, so long as there are messages in the queue, block.Set() is called so that the next message can be de-queued and another of 5 threads will work to send it. And so on, until the queue is empty. This all works OK.
However when I dispose my object, I set the disposing variable and then for each thread:
if(thread.ThreadState == ThreadState.Running)
{
thread.Join();
}
else if(thread.ThreadState == ThreadState.WaitSleepJoin)
{
thread.Abort();
}
Most of the time, the threads are sleeping due to the block.WaitOne and so the above code aborts the thread. However this causes thread abort exceptions to be logged. I could catch thread abort exceptions separately to other exceptions and choose not to log, but it doesn't seem very clean.
What is the best way to clean up these threads without causing this excess logging?
UPDATE:
I've changed the above to:
private ManualResetEvent block;
private ThreadedQueue<Message> messageQueue;
private void DoSend()
{
try
{
while(!this.disposing)
{
this.block.WaitOne();
Message message = null;
if (!this.messageQueue.TryDequeue(out message) && !this.disposing)
{
// There's nothing else to send for now to block the sending threads
// unless we're disposing as we want the other threads to exit too
this.block.Reset();
}
if(message != null)
{
this.Send(message);
}
}
}
catch(Exception ex)
{
// Log
}
}
public void Dispose()
{
this.disposing = true;
this.block.Set();
foreach(Thread thread in this.sendingThreads) {
thread.Join();
}
this.block.Dispose();
this.sendingThreads = null;
}
Thanks for the help.
You are playing a very dangerous game. Your code is particularly prone to deadlock. You'll see the thread state as ThreadState.Running and the thread calls WaitOne() a microsecond later. Your Join() call will deadlock and never return.
You can get a thread that's blocked on a WaitOne() call to unblock by disposing the AutoResetEvent. That will throw a predicable exception, ObjectDisposedException, one you can catch. Use another ManualResetEvent to signal the thread to exit. No need for Thread.Abort() that way.
Use BlockingCollection instead. it will produce simple clean and short code which can be understood, managed and debugged...
one producer five consumers... threading 101.
http://msdn.microsoft.com/en-us/library/dd267312.aspx
I have a long running method and I want to add timeout into it. Is it feasible to do that? Something like:
AbortWaitSeconds(20)
{
this.LongRunningMethod();
}
Where when it reached 20 seconds, the method will be aborted. The method doesn't have loop and I do not have a control/code over that method.
try this
class Program
{
static void Main(string[] args)
{
if (RunWithTimeout(LongRunningOperation, TimeSpan.FromMilliseconds(3000)))
{
Console.WriteLine("Worker thread finished.");
}
else
{
Console.WriteLine("Worker thread was aborted.");
}
}
static bool RunWithTimeout(ThreadStart threadStart, TimeSpan timeout)
{
Thread workerThread = new Thread(threadStart);
workerThread.Start();
bool finished = workerThread.Join(timeout);
if (!finished)
workerThread.Abort();
return finished;
}
static void LongRunningOperation()
{
Thread.Sleep(5000);
}
}
you can see it
See my answer to this question for a generic solution.
Do the calculation in a background thread and wait until the thread finishes. To abort calculation, use Thread.Abort(), this will throw a ThreadAbortException in the calculation thread.
You can only abort long running process from the same thread if you have a code point in which to introduce a check and exit. This is because - clearly - the thread is busy, so it can't process checks to abort itself. So, your example which only contains one call to 'LongRunningMethod' could not be aborted from the same thread. You'd need to show more code in order to get direction on that.
As a general rule, long-running tasks are best sent to different threads (e.g; via a BackgroundWorker or new Thread) so they can be aborted.
Here is a simple way to do this;
private void StartThread()
{
Thread t = new Thread(LongRunningMethod);
t.Start();
if (!t.Join(10000)) // give the operation 10s to complete
{
// the thread did not complete on its own, so we will abort it now
t.Abort();
}
}
private void LongRunningMethod()
{
// do something that'll take awhile
}
Since you have no control over that code I believe the correct approach would be to run that code using WaitHandles and the ThreadPool:
WaitHandle waitHandle = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(<long running task delegate>), waitHandle);
WaitHandle.WaitAll(new[]{ waitHandle }, <timeout>);
Here you can find more info on how WaitHandle works.
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();
}