what happens to ASP.NET exceptions from created non-threadpool thread? - c#

In ASP.NET web application a worker thread creates a non-threadpool thread like the below:
private static bool _refreshInProcess = false;
public delegate void Refresher();
private static Thread _refresher;
private static void CreateAndStartRefreshThread(Refresher refresh)
{
_refresher = new Thread(new ThreadStart(refresh));
_refresher.Start();
}
private static void Refresh()
{
LoadAllSystemData();
}
static public void CheckStatus()
{
DateTime timeStamp = DateTime.Now;
TimeSpan span = timeStamp.Subtract(_cacheTimeStamp);
if (span.Hours >= 24)
{
if (Monitor.TryEnter(_cacheLock))
{
try
{
if (!_refreshInProcess)
{
_refreshInProcess = true;
CreateAndStartRefreshThread(Refresh);
}
}
finally
{
Monitor.Exit(_cacheLock);
}
}
}
}
static public void LoadAllSystemData()
{
try
{
if (!Database.Connected)
{
if (!OpenDatabase())
throw new Exception("Unable to (re)connect to database");
}
SystemData newData = new SystemData();
LoadTables(ref newData);
LoadClasses(ref newData);
LoadAllSysDescrs(ref newData);
_allData = newData;
_cacheTimeStamp = DateTime.Now; // only place where timestamp is updtd
}
finally
{
_refreshInProcess = false;
}
}
and LoadAllSystemData() is also called elsewhere from the same lock-guarded section as CheckStatus(). Both calls are in their try-blocks that also have catch-block.
Now my questions are
If LoadAllSystemData throws an exception when it's called from a non-threadpool thread in method Refresh, what will happen? Nobody can catch it.
What happens when it's done 1000 times? Are these exceptions stored somewhere and thus stress the system and ultimately crash it due to memory exhaustion or something?
Is there a good solution to catch them without waiting in the creating thread pool thread for the created thread to finish?
Thanks a lot!

If exception is raised in the background non-threadpool thread and eventually it is not handled by any catch block, it is propagated up until it reaches beginning of the stack. Then thread finishes its execution - exception is not stored anywhere. Then the thread is dropped as well as its stack containing reference to the exception.
Exception throwing is expensive in .NET so if you anticipate 1000 times it to occur, probably it is not an exception but just a part of your application flow and you should not raise an exception here.
If you want to catch the exceptions from background activity, as an option you can use delegate's BeginInvoke / EndInvoke methods. If there is any exception in the background operation, it will be delivered in the EndInvoke call.

Related

Do static constructors run as CERs?

I'm testing the below code:
private static void Main()
{
var t = new Thread(() =>
{
var m = new MyCls();
m.DoWork();
});
t.Start();
// simulate time-consuming job
Thread.Sleep(1000);
t.Abort();
Console.Write("\nDone");
}
public class MyCls
{
static MyCls()
{
for (int i = 0; i < 10; i++)
{
Console.Write(i);
Thread.Sleep(1000);
}
}
public void DoWork()
{
Console.WriteLine("executing DoWork..");
}
}
And the output I get is:
0123456789
Done
It seems that t.Abort() call is blocking the main thread until the execution of the static constructor finishes, and according to the documentation:
The thread that calls Abort might block if the thread that is being aborted is in a protected region of code, such as a catch block, finally block, or constrained execution region.
My questions is:
Do static constructors really run as constrained execution regions (CERs) ?
If yes, what other code blocks that run as CERs ?
It seems that static constructors are guaranteed to have completed, almost.
Static constructors can be called explicitly with RuntimeHelpers.RunClassConstructor which 'Ensures that the type initializer (also known as a static constructor) for the specified type has been run'.
In your example, the code could be written as follows.
var t = new Thread(() =>
{
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(MyCls).TypeHandle);
var m = new MyCls();
});
RunClassConstructor calls _RunClassConstructor which is annotated with the following comment.
In the absence of class constructor deadlock conditions, the call is further guaranteed to have completed.
// RunClassConstructor causes the class constructor for the given type to be triggered
// in the current domain. After this call returns, the class constructor is guaranteed to
// have at least been started by some thread. In the absence of class constructor
// deadlock conditions, the call is further guaranteed to have completed.
//
// This call will generate an exception if the specified class constructor threw an
// exception when it ran.
[System.Security.SecuritySafeCritical]
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void _RunClassConstructor(RuntimeType type);
Update: The question is about t.Abort() blocking, not interrupting, so this answer is hardly relevant :)
The documentation for Thread.Abort Method explicitly states that Abort may abort a static constructor.
When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain.
and
For example, calling Thread.Abort may prevent static constructors from executing or prevent the release of unmanaged resources.
While your example elegantly shows that a static constructor may not be interrupted, there is no guarantee for this behaviour.
UPDATE
Here is an example where the static ctor is interrupted with Abort().
Code
public static void Main()
{
Console.WriteLine($"START");
var t = new Thread(() =>
{
var m = new MyCls();
});
Console.WriteLine($"t.Start");
t.Start();
Thread.Sleep(2000);
Console.WriteLine($"Trying to create a new object");
try
{
var m2 = new MyCls();
}
catch (Exception ex) { Console.WriteLine(ex); }
Console.WriteLine("All done");
Console.ReadLine();
}
public class MyCls
{
static MyCls()
{
for (int i = 0; i < 10; i++)
{
if (i == 4)
{
Console.WriteLine($"sctor calling Abort on itself");
Thread.CurrentThread.Abort();
};
Console.WriteLine($"sctor.{i}");
Thread.Sleep(100);
}
}
}
Output
START
t.Start
sctor.0
sctor.1
sctor.2
sctor.3
sctor calling Abort on itself
Trying to create a new object
System.TypeInitializationException: The type initializer for 'MyCls' threw an exception. ---> System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.AbortInternal()
at System.Threading.Thread.Abort()
at Program.MyCls..cctor() in c:\users\letss\source\repos\ConsoleApp2\ConsoleApp2\Program.cs:line 42
--- End of inner exception stack trace ---
at Program.MyCls..ctor()
at Program.Main() in c:\users\letss\source\repos\ConsoleApp2\ConsoleApp2\Program.cs:line 21
All done

Catch exception in current thread when it's thrown in different thread

My situation is:
from main thread i start thread A.
In main thread there some while(true) which run a lot of time. Inside of while is time consumption operations:
static void Main(string[] args)
{
new Thread(Go).Start();
while (true)
{
Thread.Sleep(1000);
}
}
private static void Go()
{
}
I wish generate exception in main thread if something go wrong in thread A
I read some articles, for example this one: catch exception that is thrown in different thread
and the only answer is: using shared variable (one of answers)
So, solution:
static void Main(string[] args)
{
new Thread(Go).Start();
while (true)
{
Thread.Sleep(1000);
if (_bad)
{
throw new Exception();
}
}
}
private static void Go()
{
Thread.Sleep(4000);
_bad = true;
}
is unacceptable, because i wish get exception ASAP. Not wait for loop cycling. For example, if i do cook cookies in while loop, i do not want wait for next cycle when i heat out: when heater is broken i wish in same moment generate exception in main thread.
Now, i can not pass delegates to thread: if i call delegate from thread A, is can not cut while loop, because it other thread. Same thing about events.
How can i handle this problem?
Thanks
The best way to achieve this is using the Task Parallel Library. If you start your task with TaskCreationOptions.LongRunning, a new thread will be created for the execution of the body of the task. You can then either access Task<T>.Result or call Wait from the main thread, and the exception (if any) will be propagated back to the thread. Use a CancellationTokenSource to support cancellation of other operations that are executing concurrently with the Go operation.
In the following example, calls to Thread.Sleep are placeholders for application-specific time consuming operations.
private static CancellationTokenSource _cancellationTokenSource =
new CancellationTokenSource();
static void Main(string[] args)
{
Task longRunning = Task.Factory.StartNew(Go, TaskCreationOptions.LongRunning);
while (true)
{
// Pass _cancellationTokenSource.Token to worker items to support
// cancelling the operation(s) immediately if the long running
// operation throws an exception
Thread.Sleep(1000);
// this will throw an exception if the task faulted, or simply continue
// if the task is still running
longRunning.Wait(0);
}
}
private static void Go()
{
try
{
Thread.Sleep(4000);
throw new Exception("Oh noes!!");
}
catch
{
_cancellationTokenSource.Cancel();
throw;
}
}
As some of the related questions suggest, use a BackgroundWorker. If the worker thread raises an exception, it gets passed to the main thread via the RunWorkerCompleted event. See http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.runworkercompleted(v=vs.110).aspx.

How best to dispose a thread that is sleeping because of AutoResetEvent.WaitOne()

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

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();
}

Can I write a C# method that will terminate execution of anyone who calls it (within the same class)?

I have a C# class that is typically executed in a thread. The caller can call a .Cancel method to stop the execution of the thread.
The ".Cancel" method will set a boolean "Cancelled" property to "True". The actual cancellation comes from little blocks like this, scattered all over the place in my code:
public void ThisGetsExecutedAsAThread()
{
.....
DoThing1;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
DoThing2;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
DoThing3;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
.....
}
This approach works quite well (i.e., the caller can cancel the action, and the execution stops within a few seconds), but as you can see it is quite repetitive.
I'd like to replace those blocks with something more like this:
...Do some action...
TerminateIfCancelled;
...Do some action....
Is it possible to define a "TerminateIfCancelled" that will cause the caller to return?
Or have I missed some much better general solution to this problem..?
Best way to end a thread is return from its function, and there are only 2 ways of returning from a function - return and throw, so if you don't like if(Cancelled) return; you can define new exception type (CancelledException for example) and throw it in your TerminateIfCancelled:
sealed class CancelledException : Exception { }
private void TerminateIfCancelled()
{
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
throw new CancelledException();
}
}
public void ThisGetsExecutedAsAThread()
{
try
{
DoThing1;
TerminateIfCancelled();
DoThing2;
TerminateIfCancelled();
DoThing3;
TerminateIfCancelled();
}
catch(CancelledException)
{
return;
}
}
C# will help you with cancel/error/continue actions if you use Task or Task<T>
Get the thread instance that you created and abort it from another thread:
Thread oThread = new Thread(new ThreadStart(someDelegate));
oThread.Start()
and on your "CancelButton_Click":
oThread.Abort()
It will raise a ThreadAbortedException on the Thread. You should catch that exception and fail gracefully.

Categories