First, I would like to describe the general structure of the classes/methods involved in my problem.
I have a class which should start a thread cyclically. This thread deals with a function which writes the log entries into a log file. I realized this with a timer (System.Threading.Timer). Further there is a ThreadHandler class which keeps all threads in a list. These threads are controlled with the standard functions of System.Threading.Thread by the name of the thread. Now to the code that is affected by my problem:
In the constructor of my Log class (LogWriter) I call the method InitializeLoggerThread():
private void InitializeLoggerThread()
{
LoggerLoggingThread = new System.Threading.Thread(new System.Threading.ThreadStart(WriteLog));
LoggerLoggingThread.Name = LoggerLogginThreadName;
ObjectObserver.ThreadHandler.AddThread(LoggerLoggingThread); // Obersver class from which all objects can be accessed
}
The Timer itself will be starte das
public void StartLogging()
{
this.LoggerTimer = new System.Threading.Timer(LoggerCallback, null, 1000, LoggerInterval);
}
Furthermore the Log class contains the implementation oft he timer:
private const int LoggerInterval = 5000;
private System.Threading.Thread LoggerLoggingThread;
private static void LoggerCallback(object state)
{
if ((BufferCount > 0))
{
ObjectObserver.ThreadHandler.StartThread(LoggerLogginThreadName);
}
}
The ThreadHandler will strart the thread with te following function:
public void StartThread(string threadName)
{
lock (Locker)
{
if (GetThread(threadName).ThreadState == ThreadState.Stopped || GetThread(threadName).ThreadState == ThreadState.Unstarted)
{
GetThread(threadName).Start();
}
}
}
I have already checked the parameters etc.. Everything is correct in this case. Basically, when debugging, it seems that the threads all try to start the logger thread at the same time.
The thread will be calles by its name with the following function:
public Thread GetThread(string threadName)
{
foreach (Thread thread in Threads)
{
if (thread.Name == threadName)
{
return thread;
}
}
return null;
}
Now to my question: What is the error in my construct that I get
System.Threading.ThreadStateException at StartThread(...)
after the first execution a multiple attempt of the execution?
If desired, I can provide a copy&paste code of all important functions for debugging.
Thread passes through a set of states (taken from here):
Once thread is completed you cannot start it again. Your timer function tries to start Stopped thread though:
if (GetThread(threadName).ThreadState == ThreadState.Stopped ...
GetThread(threadName).Start();
There are awesome logging frameworks in .NET, such as NLog and log4net, please don't try to reinvent the wheel, most likely these frameworks already can do what you need and they are doing that much more efficiently.
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.
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();
}
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.
I have the following delegate
delegate void UpdateFileDelegate(long maxFileID);
That I am calling from a WinForms app like so
UpdateFileDelegate FD = new UpdateFileDelegate(ClassInstance.UpdateFile);
FD.BeginInvoke(longIDNumber,null,null);
It runs asynchronously but the question I have is how can I tell when the Method is done executing so I can let the end user know?
Update:
Thanks to the recommendations below the following code does the trick.
Also this article was helpful in getting me to understand what my code is actually doing.
delegate void UpdateFileDelegate(long maxFileID);
UpdateFileDelegate FB = new UpdateFileDelegate(ClassInstance.UpdateFile);
AsyncCallback callback = new AsyncCallback(this.CallBackMethod);
IAsyncResult result = FB.BeginInvoke(longIDNumber);
private void CallBackMethod(IAsyncResult result)
{
AsyncResult delegateResult = (AsyncResult)result;
UpdateFileDelegate fd = (UpdateFileDelegate)delegateResult.AsyncDelegate;
fd.EndInvoke(result);
MessageBox.Show("All Done!");
}
See Calling Synchronous Methods Asynchronously
The BeginInvoke will return an IAsyncResult, which enables a number of different ways to be aware of when it is done, such as using its AsyncWaitHandle.WaitOne() method. It depends on what you are doing in the meantime.
Or you can pass a delegate for a callback method to BeginInvoke. This is arguably the most powerful strategy, but sometimes is overkill.
Calling EndInvoke on the returned IAsyncResult reference is very important. It is the only way to find out if the delegate target finished executing without any exceptions. If you don't, such an exception will fall into the bit-bucket and your program will silently fail to execute properly. You can call EndInvoke either on the same thread that called BeginInvoke() or you can do it in a callback. Calling it on the same thread rarely is useful, you'd almost always lose the benefits of asynchronous execution. Some sample code that demonstrates both and emphasizes the exception handling:
using System;
using System.Runtime.Remoting.Messaging;
class Program {
static void Main(string[] args) {
new Program().Run();
Console.ReadLine();
}
void Run() {
Action example = new Action(threaded);
IAsyncResult ia = example.BeginInvoke(new AsyncCallback(completed), null);
// Option #1:
/*
ia.AsyncWaitHandle.WaitOne();
try {
example.EndInvoke(ia);
}
catch (ApplicationException ex) {
Console.WriteLine(ex.Message);
}
*/
}
void threaded() {
throw new ApplicationException("Kaboom");
}
void completed(IAsyncResult ar) {
// Option #2:
Action example = (ar as AsyncResult).AsyncDelegate as Action;
try {
example.EndInvoke(ar);
}
catch (ApplicationException ex) {
Console.WriteLine(ex.Message);
}
}
}
You should not use a try block in the completion callback if you don't expect the code to throw exceptions. This ensures your program terminates when it does.