I currently have a class that receives information constantly from an API.
When its received that information it fires an event/delegate which other classes can subscribe to.
Because I don't want to block the thread the class is running on I use delegate.BeginInvoke to fire the event.
eg.
object UpdateLock=new object();
List<Action<object, UpdateArgs>> UpdateSubscribersList = new List<Action<object, UpdateArgs>>();
public void UpdateSubscribe(Action<object, UpdateArgs> action)
{
lock (UpdateLock)
{
UpdateSubscribersList.Add(action);
}
}
public bool UpdateUnSubscribe(Action<object, UpdatePortfolioArgs> action)
{
lock (UpdateLock)
{
return UpdateSubscribersList.Remove(action);
}
}
public virtual void onUpdate(UpdateArgs args)
{
lock (UpdateLock)
{
foreach (Action<object, UpdateArgs> action in UpdateSubscribersList)
{
action.BeginInvoke(args, null, null);
}
}
}
This is just an example. Don't worry about the use of the list rather than a multicast delegate - there's some other code which caused me to use that.
Anyway I have two questions:
1) where should I put EndInvoke so it doesn't block the thread? I believe this question has already been asked, but I'm not so clear on it, and anyway it's not my main question.
2) The main purpose of EndInvoke is to clean up the thread and handle exceptions. Now cleaning up the thread is fine, but how can I handle exceptions? I have no idea which code will be called by these delegates, and that code is not my responsibility. So is there anyway I can get the subscriber to these events to have to deal with the clean up code and the exceptions, rather than my class? Or is their anyway that he can access anything returned by EndInvoke at all, so that if he wants to he can deal with any exceptions?
I think this pattern should work for you.
public void StartAsync(Action a)
{
a.BeginInvoke(CallBack, a); // Pass a Callback and the action itself as state
// or a.BeginInvoke(Callback, null); then see alternative in Callback
}
private void CallBack(IAsyncResult ar)
{
// In the callback you can get the delegate
Action a = ar.AsyncState as Action;
// or
// Action a = ((AsyncCallback)ar).AsyncDelegate as Action
try
{
// and call EndInvoke on it.
a?.EndInvoke(ar); // Exceptions will be re-thrown when calling EndInvoke
}
catch( Exception ex )
{
Log.Error( ex, "Exception in onUpdate-Action!" );
}
}
You should be able to adapt this to your Action<object, UpdateArgs> delegate.
I used StartAsync just for brevity. This would be inside the for loop of your onUpdate Method, of course.
Mind that Callback will be called on the Async-Thread! If you want to update GUI elements here, you'll need to marshal that back to the GUI-Thread.
If you add an event to your class
public event EventHandler<Exception> OnError;
you can publish those exceptions :
catch( Exception ex )
{
Log.Error( ex, "Exception in onUpdate-Action!" );
OnError?.Invoke( a, ex );
}
Related
I'm using Unity and C# for a small project.
I have a list of person class instances, and each of them has the following method,
public void DoWork(Action onComplete) { } //onComplete is triggered when everything is done in the method.
I want to run the DoWork methods of all persons asynchronously one after the onComplete of another person DoWork is triggered. That is to say that the first person DoWork asynchronously, and after its onComplete is triggered, the second person DoWork asynchronously, go on untill all persons complete their works.
The method DoWork is currently not an async function, it would be great if I don't need to change this.
I'm wondering how shall I design the code? Is it possible to achieve the purpose without leveraging the .net Task? If not, how can I modify the DoWork method? BTW, Unity doesn't allow me to run the method in a thread (like a Task thread) that is not the main thread.
I tried the following solution. DoWork has an onComplete callback because inside it, there is a tool.Start() function which has an onComplete callback and needs to be executed, DoWork can only be done when tool.Start() onComplete is triggered. So I remoeved onComplete callback for DoWork, and wrote the following code.
public async Task DoWork()
{
bool allowExit = false;
tool.Start(() => //Start function has an Action onComplete callback, and DoWork can only be done when Start onComplete is triggered
{
allowExit = true;
});
while (!allowExit) { await Task.Yield(); }
}
public async void AllPersonsDoWork() //try to run all persons' DoWork methods asynchronously one by one
{
foreach (var person in personList)
{
await person.DoWork();
}
}
Unity3D doesn't give a threading error, but it freazes.
Any tip is appreicated, thank you very much.
As others have mentioned, you can use Queue and a method to check for Queue size and chain DoWork's to each other. but beware that if an exception occurs in one the DoWork methods all the chain of works will stop.
You can use this sample code:
public Queue<Person> TasksToDo;
public async Task CheckQueue()
{
if( TasksToDo.Count > 0){
var person = TasksToDo.Dequeue();
await person.DoWork(CheckQueue);
}
}
public class Person
{
public async Task DoWork(Func<Task> onComplete)
{
//..... do work
if (onComplete != null)
{
await onComplete();
}
}
}
First, I recommend wrapping the DoWork with a TAP wrapper. Callbacks are somewhat similar to events, so you can mostly follow this guidance. An extension method is not too difficult to write:
public static class PersonExtensions
{
public Task DoWorkAsync(this Person person)
{
var tcs = new TaskCompletionSource();
try
{
person.DoWork(() => tcs.TrySetComplete());
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}
}
The catch block above only handles synchronous errors. Asynchronous errors aren't handled, since the Action onComplete handler doesn't have a way to represent asynchronous errors. Usually, completion callbacks like this are either Action<Exception?> onComplete or Action onSuccess, Action<Exception> onFailure.
Once you have a DoWorkAsync, calling it for each person is straightforward:
async Task AllPersonsDoWork()
{
foreach (var person in personList)
await person.DoWorkAsync();
}
In the following code I have two classes, one that runs in a separate thread and fires events, the other that subscribes to this event and receives data from the event. The event code I have based off of Jon Skeet's article http://csharpindepth.com/Articles/Chapter2/Events.aspx
In this article http://www.codeproject.com/Articles/37474/Threadsafe-Events it says...
For this reason, I recommend the same approach that Jon Skeet ends up recommending at the end of Delegates and Events: "don't do that", i.e., don't use events in a multithreaded fashion. If an event exists on an object, then only one thread should be able to subscribe to or unsubscribe from that event, and it's the same thread that will raise the event.
Now obviously my design breaks that, in that it fires the event on a different thread to that it was subscribed on. How could I modify my design so that it adhears to the principle of not using events in a multi-threaded fashion or is this not possible ?
The other way I thought of doing it was just to pass in my callback method as a delegate into class B and call that instead of calling the event?
I may have completely the wrong end of the stick, so any clarification would be appreciated.
Note: I am aware that .Net 4.0 has apparently solved this issue, however I would still be interested in if there is a way to do it pre .Net 4
public delegate void MyDelegate(int a);
class A
{
void main()
{
B bObject = new B();
bObject.MyEvent += new MyDelegate(NiceMethod);
bObject.Run();
}
void NiceMethod(int a)
{
Console.Writeline({0}, a);
}
}
class B
{
readonly object eventLock = new object();
MyDelegate myDel;
public event MyDelegate MyEvent
{
add
{
lock (eventLock)
{
myDel += value;
}
}
remove
{
lock (eventLock)
{
myDel -= value;
}
}
}
//Assume this runs in a new thread and calls back data using MyEvent
//Have ommited thread code for simplicity
public void Run()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
MyDelegate handler;
lock (someEventLock)
{
handler = myDel;
}
if (handler != null)
{
handler (i);
}
}
}
}
There isn't anything wrong about raising events or listening to events from different threads. It is the responsibility of the listener to deal with being invoked from another thread. As Marc Gravell notes in his comment, adding and removing of listeners to and from events from different threads is (and always has been) supported by the compiler generated add and remove implementations. The only problem is to raise the event in a thread safe fashion, which can be done by synchronizing the access to event via the same kind of spinlock the generated add and remove are using:
class B
{
public event MyDelegate MyEvent;
protected OnMyEvent(int p_Arg)
{
// Delegates are immutable and add/remove default
// implementations always generate a new instance of the
// delegate. Therefore, tTmp (if not null) can be safely invoked
var tTmp =
System.Threading.Interlocked
.CompareExchange(ref MyEvent, null, null);
if (tTmp != null) {
tTmp(p_Arg);
}
}
//Assume this runs in a new thread and calls back data using MyEvent
//Have ommited thread code for simplicity
public void Run()
{
for (int i = 0; i < 100; i++)
{
OnMyEvent(i);
}
}
}
The only thing that could happen is that the listener is invoked after it has been removed from the event list. IMHO, the listener must be able to deal with this situation as it deals with beeing invoked from separate threads...
I've got a method which gets called frequently by different treads. Sometimes I get an AgrumenNullException when ThreadPool.QueueUserWorkItem(display(angebot), null); gets called, stating that the parameter callBack (the first parameter) is null.
What am I doing wrong?
public class ai : UserControl
{
//...
public void Display(Angebote angebot)
{
lock (_syncObj) { _current = angebot; }
ThreadPool.QueueUserWorkItem(display(angebot), null);
}
private WaitCallback display(Angebote angebot)
{
// doing something
}
//...
}
The ThreadPool.QueueUserWorkItem will do the work as defined in the WaitCallback delegate returned by display(Angebote). I would surmise that your display method sometimes returns null.
Is your intent to execute display(angebot) in the background thread, or does that method discern what method should be executed?
If you're thinking that your display method should be executing in a background thread:
private WaitCallback display(Angebote angebot)
{
// doing something in a background thread
}
Then your code should look like:
ThreadPool.QueueUserWorkItem(display, angebot);
private void display(object state)
{
Angebot angebot = (Angebot)state;
// doing something in a background thread
}
EDIT: If it's the latter where display is figuring out what background thread to execute, then perhaps you have something looking like this:
private WaitCallback display(Angebote angebot)
{
if (angebot.Something)
{
return new WaitCallback(BackgroundTask1);
}
else
{
return null;
}
}
But since you haven't posted that code, I'm not sure. In this case, returning null is invalid for ThreadPool.QueueUserWorkItem.
I have a Task which runs asynchronously and handles exceptions using a task continuation task.ContinueWith(t => ..., CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, taskScheduler).
This works great for handling exceptions I know how to handle (e.g. WebException), but what if something like NullReferenceException is thrown, which I can't handle correctly?
I want to be able to handle it using the AppDomain's unhandled exception handler (which in our case logs the error, pops up a dialog notifying the user, and exits the application), but so far I have not found a good way to do this.
Simply rethrowing the exception from the continuation results in the unhandled exception handler being called when the task is finalized (because the rethrown exception is unobserved). This is not good because it may be seconds or even minutes after I know the application should crash.
Calling Environment.FailFast() does crash the application but does not call the unhandled exception handler.
Calling Thread.CurrentThread.Abort() calls the unhandled exception handler but only displays information/the stack trace from the ThreadAbortException. Plus it just seems like a bad idea to use this method.
Calling Application.OnThreadException() actually does exactly what I want, except that it requires referencing System.Windows.Forms and handling Application.ThreadException which will not work with, for example, a service with no UI.
Calling task.Wait() does not make sense because this in our case there's no place to call it from. If the task succeeds the result is processed using a success continuation, if it fails the exception continuation is called, and we can't block the thread creating the task (that's the whole point of the task).
I could call the unhandled exception handler directly except that in at least one case that would require adding a dependency I don't want to add in my application.
Am I missing an obvious way to do this?
I didn't find any BCL class which does similar work. So, I can suggest you to use some hand-written static class:
static class Crusher
{
private static readonly AutoResetEvent CrushEvent;
private static Exception _exception;
static Crusher()
{
CrushEvent = new AutoResetEvent(false);
}
public static Thread GetCrushWaitingThread()
{
return new Thread(WaitForCrush);
}
static void WaitForCrush()
{
CrushEvent.WaitOne();
throw _exception;
}
public static void Crush(Exception exception)
{
_exception = exception;
CrushEvent.Set();
}
}
You should just init it at your application startup:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
Crusher.GetCrushWaitingThread().Start();
...
and then - you can call it from continuations:
task.ContinueWith(Continuation, TaskContinuationOptions.OnlyOnFaulted);
...
private static void Continuation(Task obj)
{
Crusher.Crush(obj.Exception);
}
But it's not as nice as real rethrown unhandled exception (it has addition information about Crusher.WaitForCrush() method in stacktrace).
We used Application.OnThreadException() to solve our specific case.
Just use the same logic that you implemented for AppDomain.UnhandledException and call it explicitly when you hit an exception in your continuation. Here is an example crash handler I use:
public static class CrashHandler
{
public static void Setup()
{
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
}
public static Task CrashOnUnhandledException(this Task t)
{
t.ContinueWith(x => HandleException(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
return t;
}
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
HandleException(e.ExceptionObject);
}
private static void HandleException(object ex)
{
ShowErrorMessage(ex);
Environment.Exit(-1);
}
private static void ShowErrorMessage(object ex)
{
// your crash dialog goes here
}
}
The extension method CrashOnUnhandledException can be used like this to save you some typing and give you additional information about the call site in your stack trace:
task.ContinueWith(t => { /* your logic */ })
.CrashOnUnhandledException();
I have a class that is a "manager" sort of class. One of it's functions is to signal that the long running process of the class should shut down. It does this by setting a boolean called "IsStopping" in class.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
// do work...
}
}
}
Now, DoWork() was a gigantic function, and I decided to refactor it out and as part of the process broke some of it into other classes. The problem is, Some of these classes also have long running functions that need to check if isStopping is true.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
MoreWork mw = new MoreWork()
mw.DoMoreWork() // possibly long running
// do work...
}
}
}
What are my options here?
I have considered passing isStopping by reference, which I don't really like because it requires there to be an outside object. I would prefer to make the additional classes as stand alone and dependancy free as possible.
I have also considered making isStopping a property, and then then having it call an event that the inner classes could be subscribed to, but this seems overly complex.
Another option was to create a "Process Cancelation Token" class, similar to what .net 4 Tasks use, then that token be passed to those classes.
How have you handled this situation?
EDIT:
Also consider that MoreWork might have a EvenMoreWork object that it instantiates and calls a potentially long running method on... and so on. I guess what i'm looking for is a way to be able to signal an arbitrary number of objects down a call tree to tell them to stop what they're doing and clean up and return.
EDIT2:
Thanks for the responses so far. Seems like there's no real consensus on methods to use, and everyone has a different opinion. Seems like this should be a design pattern...
You can go two ways here:
1) The solution you've already outlined: pass a signaling mechanism to your subordinate objects: a bool (by ref), the parent object itself cloaked in an interface (Foo: IController in the example below), or something else. The child objects check the signal as needed.
// Either in the MoreWork constructor
public MoreWork(IController controller) {
this.controller = controller;
}
// Or in DoMoreWork, depending on your preferences
public void DoMoreWork(IController controller) {
do {
// More work here
} while (!controller.IsStopping);
}
2) Turn it around and use the observer pattern - which will let you decouple your subordinate objects from the parent. If I were doing it by hand (instead of using events), I'd modify my subordinate classes to implement an IStoppable interface, and make my manager class tell them when to stop:
public interface IStoppable {
void Stop();
}
public class MoreWork: IStoppable {
bool isStopping = false;
public void Stop() { isStopping = true; }
public void DoMoreWork() {
do {
// More work here
} while (!isStopping);
}
}
Foo maintains a list of its stoppables and in its own stop method, stops them all:
public void Stop() {
this.isStopping = true;
foreach(IStoppable stoppable in stoppables) {
stoppable.Stop();
}
}
I think firing an event that your subclasses subscribe to makes sense.
You could create a Cancel() method on your manager class, and on each of your other worker classes. Base it on an interface.
The manager class, or classes that instantiate other worker classes, would have to propagate the Cancel() call to the objects they are composed of.
The deepest nested classes would then just set an internal _isStopping bool to false and your long-running tasks would check for that.
Alternatively, you could maybe create a context of some sort that all the classes know about and where they can check for a canceled flag.
Another option was to create a
"Process Cancelation Token" class,
similar to what .net 4 Tasks use, then
that token be passed to those classes.
I am not familiar with this, but if it is basically an object with a bool property flag, and that you pass into each class, then this seems like the cleanest way to me. Then you could make an abstract base class that has a constructor that takes this in and sets it to a private member variable. Then your process loops can just check that for cancellation.
Obviously you will have to keep a reference to this object you have passed into your workers so that it's bool flag can be set on it from your UI.
Your nested types could accept a delegate (or expose an event) to check for a cancel condition. Your manager then supplies a delegate to the nested types that checks its own "shouldStop" boolean. This way, the only dependency is of the ManagerType on the NestedType, which you already had anyway.
class NestedType
{
// note: the argument of Predicate<T> is not used,
// you could create a new delegate type that accepts no arguments
// and returns T
public Predicate<bool> ShouldStop = delegate() { return false; };
public void DoWork()
{
while (!this.ShouldStop(false))
{
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private bool checkShouldStop(bool ignored)
{
return shouldStop;
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.ShouldStop = checkShouldStop;
nestedType.DoWork();
}
}
You could abstract this behavior into an interface if you really wanted to.
interface IStoppable
{
Predicate<bool> ShouldStop;
}
Also, rather than just check a boolean, you could have the "stop" mechanism be throwing an exception. In the manager's checkShouldStop method, it could simply throw an OperationCanceledException:
class NestedType
{
public MethodInvoker Stop = delegate() { };
public void DoWork()
{
while (true)
{
Stop();
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private void checkShouldStop()
{
if (this.shouldStop) { throw new OperationCanceledException(); }
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.Stop = checkShouldStop;
nestedType.DoWork();
}
}
I've used this technique before and find it very effective.
Litter your code with statements like this wherever it is most sensible to check the stop flag:
if(isStopping) { throw new OperationCanceledException(); }
Catch OperationCanceledException right at the top level.
There is no real performance penalty for this because (a) it won't happen very often, and (b) when it does happen, it only happens once.
This method also works well in conjunction with a WinForms BackgroundWorker component. The worker will automatically catch a thrown exception in the worker thread and marshal it back to the UI thread. You just have to check the type of the e.Error property, e.g.:
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if(e.Error == null) {
// Finished
} else if(e.Error is OperationCanceledException) {
// Cancelled
} else {
// Genuine error - maybe display some UI?
}
}
You can flatten your call stack by turning each DoWork() call into a command using the Command pattern. At the top level, you maintain a queue of commands to perform (or a stack, depending on how your commands interact with each other). "Calling" a function is translated to enqueuing a new command onto the queue. Then, between processing each command, you can check whether or not to cancel. Like:
void DoWork() {
var commands = new Queue<ICommand>();
commands.Enqueue(new MoreWorkCommand());
while (!isStopping && !commands.IsEmpty)
{
commands.Deque().Perform(commands);
}
}
public class MoreWorkCommand : ICommand {
public void Perform(Queue<ICommand> commands) {
commands.Enqueue(new DoMoreWorkCommand());
}
}
Basically, by turning the low-level callstack into a data structure you control, you have the ability to check stuff between each "call", pause, resume, cancel, etc..