c# catch an exception from delegate.begininvoke without calling delegate.endinvoke - c#

I have a program that monitor a DB (or a number of DBs).
for this, I built a class that holds all the information about how to monitor the DB.
the class contains a delegate that points to a function that monitor the DB and changes the state field accordingly.
the main thread create a new instance of the class and calling the class.delegate.begininvoke().
the main thread checks the state of each created class in a loop and inform the user if any changes occur.
a simple example of the code:
Class Monitor
{
private Object lockObj;
private delegate void MonitorHandlerDelegate();
private MonitorHandlerDelegate mainHandler;
private int State;
private int DBid;
public Monitor(int DBid)
{
this.DBid = DBid;
mainHandler += MonitorHandler;
lockObj = new Object();
}
private void MonitorHandler()
{
do
{
state = CheckDB(DBid); // 0 is ok, 1 is fail, 2 is InWork, 3 is stop monitoring
} while (state != 3);
}
public int state
{
get { lock(lockObj) { return State;} }
set { lock(lockObj) {State = value;} }
}
public void Start()
{
this.state = 0;
this.mainHandler.BeginInvoke(null, null);
}
}
public Main()
{
Monitor firstMonitor = new Monitor(20);
firstMonitor.Start();
do
{
if(firstMonitor.state == 1) WriteLine("DB 20 stop working");
} while(true);
}
The problem I encountered is with exception handaling, if the MonitorHandler function throw an exception, i dont have a way to know it.
I dont call the EndInvoke so the exception is not re-throwing to the Main Thread.
My goal is to check the DB status by simply chack the state field of the monitor instance.
If an exception in throwen i need to somehow "transfer" this exception to the Main Thread but i dont want to start checking the state and the Monitor delegate status as well.
I whold love to find a way to the Monitor Thread itself (the one that activated by the .BeginInvoke), to throw the exception in the Main Thread.
Thank you.

I whold love to find a way to the Monitor Thread itself (the one that activated by the .BeginInvoke), to throw the exception in the Main Thread.
Other than something like ThreadAbortException, there is no mechanism to inject an exception into another arbitrary thread.
If you are going to use the delegate's BeginInvoke() method, and you want to catch the exception in a thread different from where the delegate itself is being invoked, then you will need to call EndInvoke() in that thread.
Your other option would be to deal with the exception explicitly and manually. I.e. catch the exception with try/catch in the worker thread, and then use an explicitly defined mechanism of your own choosing (e.g. a ConcurrentQueue<T>) to pass the caught exception to code running in the main thread.
All that said, using a delegate's BeginInvoke() method was never really that ideal a way to execute code asynchronously like that, and today it is even worse of an idea. It's not clear from your question what the nature of the "main thread" is, never mind whether that thread has a synchronization context. But assuming it does (e.g. it's a GUI thread, or an ASP.NET context, etc.) then your desired behavior is easily implemented using Task.Run() to start the asynchronous operation, and then using await in the main thread to capture the completion of that operation, along with any exception that is thrown.
For that matter, even if your main thread does not currently have a synchronization context, it might be the right approach is to give it one. Either by leveraging one of the existing mechanisms, or writing your own. This would be a good idea if, for example, you expect to run into this sort of "propagate the exception from the worker to the main thread" scenario in the code frequently. This would allow you to use the built-in language support for dealing with that (i.e. async/await), rather than having to kludge something for each instance. Implementing the synchronization context isn't trivial, but it's work you can do once, and then reuse over and over.

Related

Terminate parent method from child method

I create a plugin for an application.
When a user presses a stop command in the parent application, a global variable to which my plugin has access to is set to true.
For a simple method I create, I test this variable and exit:
public class Status
{
public static bool CheckTermFlag()
{
if (VoiceAttackPlugin._stopVariableToMonitor)
{
VoiceAttackPlugin._stopVariableToMonitor = false;
return true;
}
return false;
}
}
And I place this 'CheckTermFlag' in my code:
class ForTesting
{
public static void SendStopAllTest()
{
for (int i = 0; i <= 20; i++)
{
if (Status.CheckTermFlag())
{
return;
}
Thread.Sleep(500);
vaProxy.WriteToLog(i.ToString(), "Green");
}
}
The problem is that I may have several methods and each calling another one.
I can't place a question for "Status.CheckTermFlag()" in every step of my program and propagate it upwards.
So how can i 'listen' for this variable from anywhere in my program and terminate/return if required?
Why not use a CancellationToken for this? You can stop any method by any method that way. If a method have access to CTS it can just call Cancel and all methods that have CancellationTokens can then finish whatever they are doing and exit.
In multithreading environment a SemaphoreSlim can be used as an awaitable reset event as a mean of synchronizing threads.
I wouldn't use Thread.Abort(), it's good for the threads you have no control over. But if it's all your code and you control it - it's always better just to signal between threads and ask them nicely to terminate, that leads to less undefined states and behaviors later.
BTW, just make either the CancellationTokenSource accessible to methods that should stop the calling method, or made an accessible method that calls Cancel() on CTS. I used that approach a lot in a high-load network gateway and a desktop application that downloaded a large number of files parallelly. The cost of it is negligible. Don't be afraid of disposables, used correctly they save more time than it takes to handle them.
In a multi-threaded scenario the way to go is the Thread.Abort() method. It throws the ThreadAbortException in the target thread, causing it to terminate.
If you, for whatever reason, need a custom solution, do it likewise. Throw an exception, and handle it at the top-most method where it makes sense. Like this:
public class TerminateProcessingExeption : Exception { … }
…
public static bool CheckTermFlag()
{
if (VoiceAttackPlugin._stopVariableToMonitor)
{
VoiceAttackPlugin._stopVariableToMonitor = false;
throw new TerminateProcessingExeption();
}
}
In addition, instead of a bool flag, consider using an AutoResetEvent. Look into the example in the documentation for more information. A simple variable won't shield you from the adverse effects of concurrent memory access in multi-processor setups.

call method from another thread without blocking the thread (or write custom SynchronizationContext for non-UI thread) C#

This is probably one of the most frequent questions in the Stackoverflow, however I couldn't find the exact answer to my question:
I would like to design a pattern, which allows to start thread B from thread A and under specific condition (for example when exception occurs) call the method in thread A. In case of exception the correct thread matters a lot because the exception must call a catch method in the main thread A. If a thread A is an UI thread then everything is simple (call .Invoke() or .BeginInvoke() and that's it). The UI thread has some mechanism how it is done and I would like to get some insights how it would be possible to write my own mechanism for the non-UI thread. The commonly suggested method to achieve this is using the message pumping http://www.codeproject.com/Articles/32113/Understanding-SynchronizationContext-Part-II
but the while loop would block the thread A and this is not what I need and not the way how UI thread handles this issue. There are multiple ways to work around this issue but I would like to get a deeper understanding of the issue and write my own generic utility independently of the chosen methods like using System.Threading.Thread or System.Threading.Tasks.Task or BackgroundWorker or anything else and independently if there is a UI thread or not (e.g. Console application).
Below is the example code, which I try to use for testing the catching of the exception (which clearly indicates the wrong thread an exception is thrown to). I will use it as an utility with all the locking features, checking if a thread is running, etc. that is why I create an instance of a class.
class Program
{
static void Main(string[] args)
{
CustomThreads t = new CustomThreads();
try
{
// finally is called after the first action
t.RunCustomTask(ForceException, ThrowException); // Runs the ForceException and in a catch calls the ThrowException
// finally is never reached due to the unhandled Exception
t.RunCustomThread(ForceException, ThrowException);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// well, this is a lie but it is just an indication that thread B was called
Console.WriteLine("DONE, press any key");
Console.ReadKey();
}
private static void ThrowException(Exception ex)
{
throw new Exception(ex.Message, ex);
}
static void ForceException()
{
throw new Exception("Exception thrown");
}
}
public class CustomThreads
{
public void RunCustomTask(Action action, Action<Exception> action_on_exception)
{
Task.Factory.StartNew(() => PerformAction(action, action_on_exception));
}
public void RunCustomThread(Action action, Action<Exception> action_on_exception)
{
new Thread(() => PerformAction(action, action_on_exception)).Start();
}
private void PerformAction(Action action, Action<Exception> action_on_exception)
{
try
{
action();
}
catch (Exception ex)
{
action_on_exception.Invoke(ex);
}
finally
{
Console.WriteLine("Finally is called");
}
}
}
One more interesting feature that I've found is that new Thread() throws unhandled Exception and finally is never called whereas new Task() does not, and finally is called. Maybe someone could comment on the reason of this difference.
and not the way how UI thread handles this issue
That is not accurate, it is exactly how a UI thread handles it. The message loop is the general solution to the producer-consumer problem. Where in a typical Windows program, the operating system as well as other processes produce messages and the one-and-only UI thread consumes.
This pattern is required to deal with code that is fundamentally thread-unsafe. And there always is a lot of unsafe code around, the more convoluted it gets the lower the odds that it can be made thread-safe. Something you can see in .NET, there are very few classes that are thread-safe by design. Something as simple is a List<> is not thread-safe and it up to you to use the lock keyword to keep it safe. GUI code is drastically non-safe and no amount of locking is going to make it safe.
Not just because it is hard to figure out where to put the lock statement, there is a bunch of code involved that you did not write. Like message hooks, UI automation, programs that put objects on the clipboard that you paste, drag and drop, shell extensions that run when you use a shell dialog like OpenFileDialog. All of that code is thread-unsafe, primarily because its author did not have to make it thread-safe. If you trip a threading bug in such code then you do not have a phone number to call and a completely unsolvable problem.
Making a method call run on a specific thread requires this kind of help. It is not possible to arbitrarily interrupt the thread from whatever it is doing and force it to call a method. That causes horrible and completely undebuggable re-entrancy problems. Like the kind of problems caused by DoEvents(), but multiplied by a thousand. When code enters the dispatcher loop then it is implicitly "idle" and not busy executing its own code. So can take an execution request from the message queue. This can still go wrong, you'll shoot your leg off when you pump when you are not idle. Which is why DoEvents() is so dangerous.
So no shortcuts here, you really do need to deal with that while() loop. That it is possible to do so is something you have pretty solid proof for, the UI thread does it pretty well. Consider creating your own.

Weird InvokeRequired issue

I have a UserControl with a TreeView control called mTreeView on it. I can get data updates from multiple different threads, and these cause the TreeView to be updated. To do this, I've devised the following pattern:
all data update event handlers must acquire a lock and then check for InvokeRequired; if so, do the work by calling Invoke. Here's the relevant code:
public partial class TreeViewControl : UserControl
{
object mLock = new object();
void LockAndInvoke(Control c, Action a)
{
lock (mLock)
{
if (c.InvokeRequired)
{
c.Invoke(a);
}
else
{
a();
}
}
}
public void DataChanged(object sender, NewDataEventArgs e)
{
LockAndInvoke(mTreeView, () =>
{
// get the data
mTreeView.BeginUpdate();
// perform update
mTreeView.EndUpdate();
});
}
}
My problem is, sometimes, upon startup, I will get an InvalidOperationException on mTreeView.BeginUpdate(), saying mTreeView is being updated from a thread different than the one it was created. I go back in the call stack to my LockAndInvoke, and lo and behold, c.InvokeRequired is true but the else branch was taken! It's as if InvokeRequired had been set to true on a different thread after the else branch was taken.
Is there anything wrong with my approach, and what can I do to prevent this?
EDIT: my colleague tells me that the problem is that InvokeRequired is false until the control is created, so this is why it happens on startup. He's not sure what to do about it though. Any ideas?
It is a standard threading race. You are starting the thread too soon, before the TreeView is created. So your code sees InvokeRequired as false and fails when a split second later the native control gets created. Fix this by only starting the thread when the form's Load event fires, the first event that guarantees that all the control handles are valid.
Some mis-conceptions in the code btw. Using lock is unnecessary, both InvokeRequired and Begin/Invoke are thread-safe. And InvokeRequired is an anti-pattern. You almost always know that the method is going to be called by a worker thread. So use InvokeRequired only to throw an exception when it is false. Which would have allowed diagnosing this problem early.
When you marshal back to the UI thread, it's one thread--it can do only one thing at at time. You don't need any locks when you call Invoke.
The problem with Invoke is that it blocks the calling thread. That calling thread usually doesn't care about what get's completed on the UI thread. In that case I recommend using BeginInvoke to marshal the action back to the UI thread asynchronously. There are circumstances where the background thread can be blocked on Invoke while the UI thread can be waiting for the background thread to complete something and you end up with a deadlock: For example:
private bool b;
public void EventHandler(object sender, EventArgs e)
{
while(b) Thread.Sleep(1); // give up time to any other waiting threads
if(InvokeRequired)
{
b = true;
Invoke((MethodInvoker)(()=>EventHandler(sender, e)), null);
b = false;
}
}
... the above will deadlock on the while loop while because Invoke won't return until the call to EventHandler returns and EventHandler won't return until b is false...
Note my use of a bool to stop certain sections of code from running. This is very similar to lock. So, yes, you can end up having a deadlock by using lock.
Simply do this:
public void DataChanged(object sender, NewDataEventArgs e)
{
if(InvokeRequired)
{
BeginInvoke((MethodInvoker)(()=>DataChanged(sender, e)), null);
return;
}
// get the data
mTreeView.BeginUpdate();
// perform update
mTreeView.EndUpdate();
}
This simply re-invokes the DataChanged method asynchronously on the UI thread.
The pattern as you have shown it above looks 100% fine to me (albeit with some extra unnecessary locking, however I can't see how this would cause the problem you have described).
As David W points out, the only difference between what you are doing and this extension method is that you directly access mTreeView on the UI thread instead of passing it in as an argument to your action, however this will only make a difference if the value of mTreeView changes, and in any case you would have to try fairly hard to get this to cause the problem you have described.
Which means that the problem must be something else.
The only thing that I can think of is that you may have created mTreeView on a thread other than the UI thread - if this is the case then accessing the tree view will be 100% safe, however if you try and add that tree view to a form which was created on a different thread then it will go bang with an exception similar to the one that you describe.

Sending an exception from thread to main thread?

I want to pass an exception from current thread (that thread isn't main thread)to main thread.
Why? Because I check my hard lock in another thread (that thread use timer for checking), and when HardLock is not accessible or invalid, I create an exception which is defined by myself and then throw that exception.
So that exception doesn't work well. ;(
Your best bet is to replace the Thread with a Task (new in .NET 4.0). The Task class handles proper marshaling of the exception to whatever thread checks the result of the task.
If using .NET 4.0 is not possible, then CoreEx.dll from the Rx extensions includes an Exception.PrepareForRethrow extension method that preserves the call stack for exceptions. You can use this in conjunction with MaLio's suggestion of SynchronizationContext to marshal an exception to another thread.
You can use the exception as an parameter in event.
And handle it after sending the exception to other thread.
Code example.
public delegate void SendToMainDel(string threadName,Exception ex);
public event SendToMainDel SendToMainEv;
public void MySecondThread()
{
try
{
....
}catch(Exception ex)
{
if(SendToMainEv!=null)
SendToMainEv("MySecondThread",ex);
}
}
...
SendToMainEv += ReceiveOtherThreadExceptions;
...
public void ReceiveOtherThreadExceptions(string threadName,Exception ex)
{
if(InvokeRequired)
{
BeginInvoke(new SendToMainDel(ReceiveOtherThreadExceptions), threadName, ex);
return;
}
//there you can handle the exception
//throw ex;
}
Knowing nothing else, it seems like your locking is broken, if you need a thread to ensure that your locks aren't held too long or are invalid.
If you really need to throw exceptions to your main thread, set up a communication queue from all your 'worker threads' to your 'master thread', and wrap your entire worker threads in an exception handler that does nothing more than append exceptions to the queue and then kills that thread. Your master thread can poll the queue to discover exceptions and restart threads that have died after correcting the error condition.
Pass along a reference to the execution context of the main form to the thread (via the delegate or field). Then invoke a method (either send or post) via that synchronization context from your thread that throws the exception. The execution context will ensure it is processed by the ui thread.
You might find it easier to keep the exception handling within the thread and pass back the exception message and stack trace by returning MyException.ToString() in a callback. When I get exceptions from another thread, everything I'm looking for is in that string.
Just my 2 cents.
I think you can use Invoke, BeginInvoke on the main form if you are running Windows Forms to send an exception there from try/catch block. Or you can create an event handler/delegate in a main thread and send exceptions through that to the main thread so the method in a main thread can process it. To be honest haven't tried those solutions but those are my first ideas.
PS. Maybe creating a WorkerQueue on the main thread is also an option. It will run as a backgroundWorker and when it gets new exception sent in it processes it accordingly... I can give you small examples on that if you're interested.
Edit:
public class JobQueue
{
private Queue<Exception> pendingJobs = new Queue<Exception>();
private Exception defaultJob = null;
bool run = true;
public void AddJob(Exception job)
{
pendingJobs.Enqueue(job);
}
public JobQueue()
{
defaultJob=null;
}
public void StopJobQueue()
{
run = false;
}
public void Run()
{
while (run)
{
Exception job = (pendingJobs.Count > 0) ? pendingJobs.Dequeue() : defaultJob;
if (job!= null)
{
////what to do with current Exception
}
Thread.Sleep(20); //I know this is bad...
}
pendingJobs.Clear();
}
}
}
To use it:
In your main thread class:
private JobQueue m_jobQueue;
In Initialize() or wherever your main thread starts:
Backgroundworker bw = new Backgroundworker();
bw.DoWork+= jobQueue.Run;
bw.StartAsync();
//m_jobQueue = new JobQueue();
// new Thread(new ThreadStart(jobQueue.Run)).Start();
And to send an exception use:
m_jobQueue.AddJob(StackOverflowException);
Stop by:
m_jobQueue.StopJobQueue();

Is it possible to put an event handler on a different thread to the caller?

Lets say I have a component called Tasking (that I cannot modify) which exposes a method “DoTask” that does some possibly lengthy calculations and returns the result in via an event TaskCompleted. Normally this is called in a windows form that the user closes after she gets the results.
In my particular scenario I need to associate some data (a database record) with the data returned in TaskCompleted and use that to update the database record.
I’ve investigated the use of AutoResetEvent to notify when the event is handled. The problem with that is AutoResetEvent.WaitOne() will block and the event handler will never get called. Normally AutoResetEvents is called be a separate thread, so I guess that means that the event handler is on the same thread as the method that calls.
Essentially I want to turn an asynchronous call, where the results are returned via an event, into a synchronous call (ie call DoSyncTask from another class) by blocking until the event is handled and the results placed in a location accessible to both the event handler and the method that called the method that started the async call.
public class SyncTask
{
TaskCompletedEventArgs data;
AutoResetEvent taskDone;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
taskDone.WaitOne(); // but something more like Application.DoEvents(); in WinForms.
taskDone.Reset();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
taskDone.Set(); //or some other mechanism to signal to DoSyncTask that the work is complete.
}
}
In a Windows App the following works correctly.
public class SyncTask
{
TaskCompletedEventArgs data;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
while (data == null) Application.DoEvents();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
}
}
I just need to replicate that behaviour in a window service, where Application.Run isn’t called and the ApplicationContext object isn’t available.
I've had some trouble lately with making asynchronous calls and events at threads and returning them to the main thread.
I used SynchronizationContext to keep track of things. The (pseudo)code below shows what is working for me at the moment.
SynchronizationContext context;
void start()
{
//First store the current context
//to call back to it later
context = SynchronizationContext.Current;
//Start a thread and make it call
//the async method, for example:
Proxy.BeginCodeLookup(aVariable,
new AsyncCallback(LookupResult),
AsyncState);
//Now continue with what you were doing
//and let the lookup finish
}
void LookupResult(IAsyncResult result)
{
//when the async function is finished
//this method is called. It's on
//the same thread as the the caller,
//BeginCodeLookup in this case.
result.AsyncWaitHandle.WaitOne();
var LookupResult= Proxy.EndCodeLookup(result);
//The SynchronizationContext.Send method
//performs a callback to the thread of the
//context, in this case the main thread
context.Send(new SendOrPostCallback(OnLookupCompleted),
result.AsyncState);
}
void OnLookupCompleted(object state)
{
//now this code will be executed on the
//main thread.
}
I hope this helps, as it fixed the problem for me.
Maybe you could get DoSyncTask to start a timer object that checks for the value of your data variable at some appropriate interval. Once data has a value, you could then have another event fire to tell you that data now has a value (and shut the timer off of course).
Pretty ugly hack, but it could work... in theory.
Sorry, that's the best I can come up with half asleep. Time for bed...
I worked out a solution to the async to sync problem, at least using all .NET classes.
Link
It still doesn't work with COM. I suspect because of STA threading. The Event raised by the .NET component that hosts the COM OCX is never handled by my worker thread, so I get a deadlock on WaitOne().
someone else may appreciate the solution though :)
If Task is a WinForms component, it might be very aware of threading issues and Invoke the event handler on the main thread -- which seems to be what you're seeing.
So, it might be that it relies on a message pump happening or something. Application.Run has overloads that are for non-GUI apps. You might consider getting a thread to startup and pump to see if that fixes the issue.
I'd also recommend using Reflector to get a look at the source code of the component to figure out what it's doing.
You've almost got it. You need the DoTask method to run on a different thread so the WaitOne call won't prevent work from being done. Something like this:
Action<int, int> doTaskAction = t.DoTask;
doTaskAction.BeginInvoke(latitude, longitude, cb => doTaskAction.EndInvoke(cb), null);
taskDone.WaitOne();
My comment on Scott W's answer seems a little cryptic after I re-read it. So let me be more explicit:
while( !done )
{
taskDone.WaitOne( 200 );
Application.DoEvents();
}
The WaitOne( 200 ) will cause it to return control to your UI thread 5 times per second (you can adjust this as you wish). The DoEvents() call will flush the windows event queue (the one that handles all windows event handling like painting, etc.). Add two members to your class (one bool flag "done" in this example, and one return data "street" in your example).
That is the simplest way to get what you want done. (I have very similar code in an app of my own, so I know it works)
Your code is almost right... I just changed
t.DoTask(latitude, longitude);
for
new Thread(() => t.DoTask(latitude, longitude)).Start();
TaskCompleted will be executed in the same thread as DoTask does. This should work.

Categories

Resources