in my class i use a BackgroundWorker. at some point i need to cancel the asynchronous operation that can be in progress and start another one immediately. the code follows. one thing that i am not sure about is the race condition that can occur if the worker completes right before i assign my lambda to RunWorkerCompleted event. if this happens my lambda will never get called. the comment in the code shows this place. any comments on how to handle this?
thanks
konstantin
if (this.worker.IsBusy)
{
RunWorkerCompletedEventHandler f = null;
f = (s, v) =>
{
this.RunWorkerCompleted -= f;
this.worker.RunWorkerAsync();
};
// what if worker completes right before the following statement?
this.worker.RunWorkerCompleted += f;
this.worker.CancelAsync();
}
else
{
this.worker.RunWorkerAsync();
}
As long as this code runs on the main thread then there is no race. A BGW can only complete when the RunWorkerCompleted event handler finished running. The handler cannot start running until the main thread re-enters the message loop.
There's another kind of race though, induced by the else clause. You let the BGW start without a RunWorkerCompleted event handler. Now it can complete asynchronously since it won't be blocked. Always subscribe the event, test e.Cancelled to know what happened.
You could just add the RunWorkerCompleted event handler once in the ctor and also add a bool member variable 'restart' to the class. Then you can write if(IsBusy) restart = true and in your handler you check if(restart) Run(). You can define restart as volatile to avoid race conditions in that case.
I think it is not a good practice to add and remove event handlers in your case.
Maybe i'm just not smart enough to understand your code. But in my world i would built up a Queue<Action> and fill in all jobs that have to be done.
Another thread (or BackgroundWorker) will take a look at this Queue and process all the jobs in the queue sequentially (like my answer here). Maybe this is not very elegant due to the pull-mode by using a Thread.Sleep(1) in a loop.
But this could be accomplished by creating a BindingQueue<T> that derived from Queue<T> and implements IBindingList. So you could just wait for such an event, dequeue and invoke an Action till the queue is empty and start over again.
Related
In my application I have a queue which fires notifications whenever there are any changes to the queue, but sometimes it happens that when there are simultaneous operations on the queue event handler that it fires multiple times and that's okay, but what I don't want is,...
Below is the code for the event handler:
private async void NotificationQueue_Changed(object sender, EventArgs e)
{
if (!IsQueueInProcess)
await ProcessQeueue();
}
In ProcessQueue method I am setting IsQueueInProcess to true and whenever it gets completed it is set to false. Now, the problem is that whenever multiple event notifications fire simultaneously multiple ProcessQeueue methods start executing, which I don't want. I want to make sure that there will be only one execution of ProcessQeueue at any given time.
Given your statement that this event is raised whenever there are any changes to the queue, and that the queue can be used concurrently (i.e. there are multiple producers adding things to the queue), it seems likely to me that the best way to address this would be to abandon the event-based behavior altogether. Instead, using BlockingCollection<T>, with a thread dedicated to processing the queue via GetConsumingEnumerable(). That method will block the thread as long as the queue is empty, and will allow the thread to remove and process items in the queue any time any other thread adds something to it. The collection itself is thread-safe, so using that you would not require any additional thread synchronization (for the handling of the queue, that is…it's possible processing an item involves thread interactions, but there's nothing in your question that describes that aspect, so I can't say one way or the other anything about that).
That said, taking the question literally, the simplest approach would be to include a semaphore:
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
private async void NotificationQueue_Changed(object sender, EventArgs e)
{
if (_semaphore.Wait(0))
{
await ProcessQueue();
_semaphore.Release();
}
}
The above attempts to acquire the semaphore's lock. With a timeout of 0 milliseconds, it will return immediately even if the semaphore could not be acquired. The return value indicates whether the semaphore was successfully acquired or not.
In this way, as long as there is no outstanding queue-processing operation, the current event handler invocation can acquire the semaphore and will call the ProcessQueue() method. When that operation completes, the continuation will release the semaphore. Until that happens, no other invocation of the event handler will be able to acquire the semaphore, and thus will not initiate processing of the queue.
I'll note that nothing here guarantees a solution to threads racing with each other that would ensure the queue is always either empty, or always has some processing operation acting on it. That's up to you, to ensure that the ProcessQueue() method has the synchronization needed to guarantee that if any thread has modified the queue and caused this event to be raised, that that thread will not fail to initiate another round of processing should the first round not be able to observe the change.
Or put another way, you need to make sure that for any thread that is going to raise that event, either its change to the queue will be observed by the current processing operation, or that thread will initiate a new one.
There's not enough context in your question for anyone to be able to address that concern specifically. I will just point out that it's a common enough thing for someone to overlook when trying to implement this sort of system. IMHO, all the more reason to just have a dedicated thread using BlockingCollection<T> to consume elements added to the queue. :)
See also the related question How to avoid reentrancy with async void event handlers?. This is a slightly different question, in that the accepted answer causes each invocation of the event handler to result in the operation initiated by the event handler. Your scenario is simpler, since you simply want to skip initiation of a new operation, but you may still find some useful insight there.
I agree with Peter that abandoning event-based notifications is the best solution, and that you should move to a producer/consumer queue. However, I recommend one of the TPL Dataflow blocks instead of BlockingCollection<T>.
In particular, ActionBlock<T> should work quite nicely:
private readonly ActionBlock<T> notificationQueue = new ActionBlock<T>(async t =>
{
await ProcessQueueItem(t);
});
By default, TPL Dataflow blocks have a concurrency limit of 1.
Imagine you have some routine that registers as BeginInvoke to the ApplicationIdle, for example
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)OffLoadWork);
Now in certain scenarios this OffLoadWork needs to be executed when doing a operation in the UI, for example on a button click, is it safe for me to call
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.ApplicationIdle, (Func<object>)(() =>
{
//do nothing just wait for the OffLoadWork to happen...
return null;
}));
or can it occur that my UI freezes, since I am in the middle of an UI Operation so when does it actually get Idle?
In my first test, it seemed to work but I just want to make sure that there isn't a way for it to freeze/block.
I think you are confusing DispatcherPriority.ApplicationIdle. Invoke is sync and can block your UI.
DispatcherPriority here as per the definition is the priority, relative to the other pending operations in the Dispatcher event queue, the specified method is invoked. So if your operation is the only one happening in the Dispatcher queue and triggered on UI thread it will block it till the time it does not return.
How is this code going to behave through processing time ? (i.e, how synchronous is it ?)
public delegate void FooDelegate(bytes[] data);
public event FooDelegate FooEvent;
FooEvent += new FooDelegate(Process_X);
FooEvent += new FooDelegate(Process_Y);
FooEvent += new FooDelegate(Process_Z);
while (receiving)
{
byte[] data = getRealTimeData();
StopWatch.Start();
FooEvent(data);
StopWatch.Stop();
Console.Write(StopWatch.Elapsed.Millisec));
StopWatch.Reset();
}
I have a couple of questions :
Will the call to FooEvent result in calling each subscription process sequentially/synchornously ? (Probably yes...)
Assuming each Process_N takes a long while to finish, will the call to each one block the chain (i.e the call to the next one) until it has finished ? If this is true, How to make the event call Processes X, Y, Z in a parallel fashion an then wait for all of them to finish, rather than calling them one by one and sequentially waiting for each one to finish ?
A few confirmations :
If the number of subscribers gets very high, I guess the Time printed by the StopWatch will get higher
If the processing logic in Process_N gets heavier, it will also affect the Time printed by the StopWatch
It looks like you'd benefit from parallelisation of your event handlers, as they will indeed execute sequentially and synchronously.
To create your custom event handlers you might write:
public event FooDelegate FooEvent
{
add
{
// code to add an event handler
}
remove
{
// code to remove an event handler
}
}
See the following questions for more information on what to do with the custom event handlers:
Events with Task Parallel Library for .NET 4+
How to process events in parallel
Parallel event handling in C#
etc.
and Jon Skeet's page on delegates and events.
1: yes
2: yes
It has to events might return results.
But: you should implement your event-handlers in a way so that they don't take long to run!
If they have to do heavy lifting consider running the computation in a task that get's started in your event-handeler.
I'm a newbie to C# and multithreading so I apologise if this is a duplicate question but being a novice it appears my question is slightly different to others I have read.
My GUI runs in one (main) thread. It calls a background task (in a dll -- that I am writing too) that runs in a separate thread. The dll has NO knowledge of the GUI (i.e. it cannot reference the GUI class).
Now, say I want to update a progress bar on the GUI based on the status of the dll thread -> What I'm doing is creating an event in the dll that every X per cent will fire and the GUI will subscribe to this event. When the event is fired, the GUI will update the progress bar.
My questions:
Is the method of creating events the best way (bearing in mind the dll cannot reference the GUI)?
How do I ensure my above method is 'event safe'? Should I pass the progress percentage in the event to be thread safe or is there more to it?
Do I need to use Invoke when updating the GUI? I saw a post that suggested I did but I don't understand why since the updating of the bar is being done in the GUI thread??!
Hope you can clarify this for me!
Thanks
1.-I use that method all the time and yes it will work
2.-Just pass a int to the event handler and the variable will be safe to read. however when you are fireing the event from code do it like this
private void UpdatePercentage(int a)
{
var myEvent = PercentageUpdatedEvent
if(myEvent != null)
myEvent(this, new ProgressBarEventArgs(a));
}
The reason for this is so if the event is unsubcribed between the null check and the calling you won't get a exception.
3.-As everyone else has mentioned you will need to call Invoke as the event will be running on the dll's thread. However with controls it is legal to call a BeginInvoke without a EndEnvoike so the call will be non blocking on the dll's thread.
Here is the pattern I always use
private myClass_OnPercentageUpdatedEvent(object a, ProgressBarEventArgs e)
{
if(progressBar.InvokeRequired)
progressBar.BeginInvoke((Action<object,ProgressBarEventArgs>)myCless_OnPercentageUpdatedEvent, a, e);
else
{
progressBar.Value = e.Value;
}
}
Look into the BackgroundWorker class. It sounds like it fits your scenario pretty well.
This link on MSDN explains how to use it: http://msdn.microsoft.com/en-us/library/cc221403%28VS.95%29.aspx
Keep in mind that under most circumstances, the events raised from your background task will also run on the background thread. No thread context switch happens automatically at all.
To understand why, you have to consider what an event is; just a certain type of Delegate object. You are setting a Delegate to that event from the main thread... but that delegate will actually be called within the background thread, in the code that triggers the event.
So yes; you would need to make sure you are moving things over to run on the GUI thread from within that event handler.
To answer (3) you will need to use Invoke. The event-handlers are going to be run from the background thread, not the GUI thread.
If you spin off a thread, you need to create a delegate, that can safely invoke your main thread with the appropriate parameters.
delegate void UpdateDelegate(int val)
void Update(int val)
{
if(this.InvokeRequired())
{
Invoke(new UpdateDeleage(Update),new object[] {val});
return;
}
this.MyProgressBar.Value = val;
}
Call Update from your separate thread as you would if calling it from your main thread. Once the thread determines that your main thread needs invoked to pass the value, it will invoke it with your delegate, with the parameters you passed. Otherwise, it will simply skip the block and set your values.
e.g.
...
new Thread(()=>IncrementValues()).Start();
...
void IncrementValues()
{
while(true)
Update(new Random(0,10));
}
I have on my blog a few different approaches to this problem, with the advantages/disadvantages of each. In summary, I recommend using the Task class.
I have following problem:
I want to check (C#) if a thread has finished execution, i.e. if the thread method has returned. What I do now is call Thread.Join(1), but this gives a 1 ms delay. Is there any way to simply check if a thread has finished. Inspecting Thread.ThreadState just seems too cumbersome.
Use the Thread.IsAlive flag. This is to give the thread status.
For a thread you have the myThread.IsAlive property. It is false if the thread method returned or the thread was aborted.
If you don't want to block the current thread by waiting/checking for the other running thread completion, you can
implement callback method like this.
Action onCompleted = () =>
{
//On complete action
};
var thread = new Thread(
() =>
{
try
{
// Do your work
}
finally
{
onCompleted();
}
});
thread.Start();
If you are dealing with controls that doesn't support cross-thread operation, then you have to invoke the callback method
this.Invoke(onCompleted);
You could fire an event from your thread when it finishes and subscribe to that.
Alternatively you can call Thread.Join() without any arguments:
Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping.
Thread.Join(1) will:
Blocks the calling thread until a thread terminates or the specified time elapses, while continuing to perform standard COM and SendMessage pumping.
In this case the specified time is 1 millisecond.
Use Thread.Join(TimeSpan.Zero) It will not block the caller and returns a value indicating whether the thread has completed its work. By the way, that is the standard way of testing all WaitHandle classes as well.
I use IsAlive extensively, unless I want to block the current execution (of the calling thread), in which case I just call Join() without a parameter. Now, be aware that IsAlive may return false if the target thread has not actually started execution yet for any reason.
Carlos Merighe.
It depends on how you want to use it. Using a Join is one way. Another way of doing it is let the thread notify the caller of the thread by using an event. For instance when you have your graphical user interface (GUI) thread that calls a process which runs for a while and needs to update the GUI when it finishes, you can use the event to do this. This website gives you an idea about how to work with events:
http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx
Remember that it will result in cross-threading operations and in case you want to update the GUI from another thread, you will have to use the Invoke method of the control which you want to update.
Take a look at BackgroundWorker Class, with the OnRunWorkerCompleted you can do it.