I'm using Background Worker i'm having problem with RunWorkerCompleted event he is firing too late. My DoWork method finished all operations and then main therad working, after all operation in main thread RunWorkerCompleted is firing. Is it normal? Should RunkWorkerCompleted not firing after DoWork method. Is it possible to exact RunWorkerCompleted instant DoWork method?
As the documentation states:
This event is raised when the DoWork event handler returns.
So your method is running longer thn you expect I guess.
You could use RunWorkerCompletedEventArgs and check if method was run successfully.
Documntation also includes how to use it.
Related
I just want to know why TimerTick event handler is handled by the UI Thread and the DataReceived Event is handled by a worker thread. I thought they both are an event and handled by the UI thread. I tried Thread.Sleep(5000) when Data received event handler method is handled but the UI thread and form controls didn't freeze, yet when I tried the same inside timertick event handler, it blocks the UI thread and form control objects.
Is there a way to make timertick event work just like datareceived event (in a separate thread)?
Can anyone tell me in WPF why we need to use Dispatcher.BeginInvoke() method to update UI from DoworkEvent handler when we can update UI using ProgressChangedEvent event handler by calling ReportProgress() method in DoWork event Eventhandler?
Correct me if my understanding about Background worker and dispatcher are incorrect?
There's one rule you need to remember:
Updating the UI needs to be done from the UI thread.
Keeping this in mind, let's see what the dispatcher does and what the backgroundworker does:
Dispatcher
The dispatcher is an object that, when you call BeginInvoke, will execute the method on the thread the dispatcher was created. The Application's dispatcher is always created on the UI thread, hence this will work.
Background worker
The background worker is very similar, although it offers an event-based API:
When you call ReportProgress inside the DoWork-method, the BackgroundWorker will raise an event on the thread the background-worker was created. So if you create the Background-Worker on the UI thread, you can update the UI inside the ProgressChanged event handler.
You can safely update the UI from a BackgroundWorker's ProgressChanged handler without any need for calling the Dispatcher.
The ProgressChanged event will by raised whenever you call ReportProgress. It is executed on the thread that created the BackgroundWorker instance, which is usually the UI thread.
From the Remarks section in ReportProgress:
The call to the ReportProgress method is asynchronous and returns
immediately. The ProgressChanged event handler executes on the thread
that created the BackgroundWorker.
I have an event that is fired async via BeginInvoke - so the event handler gets its own threadpool thread. But all the code in the event handler wants to be dispatched to the UI thread - so the entire event handler code is in a Dispatcher.BeginInvoke block. This means:
Initiating thread fires event with BeginInvoke.
A new threadpool thread is created for the event handler code to run on.
The event handler immediately just posts its code async to the UI thread using
the dispatcher (Dispatcher.BeginInvoke(...all handler code...).
The temp threadpool thread returns quasi immediately - its created only to do a UI thread post.
Is there any way to restructure this to avoid the creation of this very short lived intermediate threadpool thread (I.e so the handler code just runs directly on the UI thread)?
I dont want the event to fire sycnronously (Invoke) - its used in various contexts - and it shouldn't be blocking.
Can you just call Dispatcher.BeginInvoke directly instead of using a threadpool thread?
If you don't control the code that fires the event you don't really have a choice; there is no way around the use of the thread pool thread for that short duration.
If you do control the code that fires the event you have the option of ensuring that the event handlers all run in the UI thread. While this is certainly possible, you should think long and hard about whether it should be the case. For certain event handlers it just makes sense for them to run in the UI thread (as an example, most of the events of Form run in the UI thread) and some it doesn't. If your event is on a UI control it probably makes sense for it to run in the UI thread. If it's an event of some worker class that you just happen to be using from a UI thread at the moment, it's probably a bad idea to fire the event in the UI thread (as you may, in the future, be using that worker context in a non-WPF context).
If you do want to fire the event in the UI thread it's simple enough. If you are already in the UI thread when you intend to fire the event just invoke it synchronously:
var eventCopy = MyEvent;
if(eventCopy != null) eventCopy();
If you're not in the UI thread when you wish to fire the event then marshal to the UI thread before calling the above code:
Dispatcher.BeginInvoke(()=>{ //Or just `Invoke`, if that's appropriate in context
var eventCopy = MyEvent;
if(eventCopy != null) eventCopy();
});
Based on your edit it seems you want to conditionally fire the event in the UI thread or a thread pool thread based on some specific context, rather than always firing in the UI thread.
While this is possible, you'll need to decide if it's worth it.
As an example you could look at System.Timers.Timer which has a SynchronizingObject property that allows you to determine how the events are rasied (null for the thread pool, or an object capable of marshalling to a particular context in the event of a particular UI model).
You could follow that general pattern.
There are a number of specific methods. You could capture the value in SynchronizationContext.Current at the time your worker thread was first created, and use that (possibly with a boolean value to disable capturing the source sync context if you might need to disable it, or forcably enable it).
Another option is to just have a property that accepts a SynchronizationContext, or some other mechanism of marshalling code to a given context (you could invent your own, use delegates, etc.).
Does the blocking of a thread also blocks the firing and/or propagation of event fired from it?
To clarify:
On a thread I am firing an event and as a next step I let the thread fall asleep. The question is whether the firing - if stated immediately before the statement to go sleep - is also blocked to fire due to a scheduling issue (i.e. the event has been scheduled to fire but actual firing will take place in say 100 ms and before these 100 ms have been passed the thread has been fall asleep).
// Pseudo-Code
event MyHandler TheEvent;
// ...
TheEvent();
threadWaitingSignal.Wait(); // block the thread
What assumptions can I make in the above scenario regarding the firing and the delivery of the event to its subscribers ?
All listeners will receive the event before the thread sleeps. Events are fired synchronously.
Does SqlDependency (for example) fires the OnChange event, when the invocation of previous event handler didn't finish? (Assume that OnDependencyChange method is very time consuming)
What exactly happens?
SqlDependency dependency=new SqlDependency(command);
// Subscribe to the SqlDependency event.
dependency.OnChange += new
OnChangeEventHandler(OnDependencyChange);
I am not that familiar with the SqlDependency class, but per the MSDN documenation:
The OnChange event may be generated on
a different thread from the thread
that initiated command execution.
That seems to open up the possibility that two event handlers can run simultaneously. There is no documentation that states that all event handlers invoked from raising the event must complete before the event can be raised again. The safe thing to do is to assume multiple simultaneous invocations of the event can occur. Because the event is raised on an undefined thread you will have to guard against the problems of concurrency anyway.
In normal single threaded program not it will not. Try following:
Add windows forms app. Add a button to a form. Use following method to handle button's click event:
private void Buttonclick(object sender, EventArgs e)
{
Thread.Sleep(25);//SUSPEND CURRENT THREAD
}
you will not be able to click the button until the call to Thread.Sleep(25) finishes its work (suspend thread for 25 secs). You can test this in Console app also.