I have a background worker which updates the GUI on a regular basis via ReportProgress.
The update occurs at regular intervals, every 5 seconds for example, or it c
Or even better, use the Reactive Extensions framework and have a "worker" observe a stream of interval events. The stream can then easily be disposed to stop generating new events, thus terminating the worker. Combine this with a cancellation disposable and you have one single disposable to stop both the interval timer and any worker doing its work:
var cancel = new BooleanDisposable();
var subscription = Observable.Interval(TimeSpan.FromSeconds(20))
.ObserveOn(Scheduler.DispatcherScheduler)
.Subscribe(i => PerformWorkOnUI(cancel));
var uiWork = new CompositeDisposable(cancel, subscription);
To cancel the stream of timer events, you only have to dispose the composite cancellation/subscription:
uiWork.Dispose();
Clarification: ObserveOn(Scheduler.DispatcherScheduler)
ensures that the subscription will be called on the dispatcher thread.
You can use a ManualResetEvent to both allow your thread to wait without polling and to allow another thread to wake it up any anytime.
The ManualResetEvent
as well as any of the other thread synchronization objects has a WaitOne
method that can wait for the event to be set or for a time out. So normally you can have WaitOne
wait for the amount you want to wait for (which will work like a Thread.Sleep
) but the main thread can wake up the background thread at any time.
ManualResetEvent backgroundWakeEvent = new ManualResetEvent(false);
....
bkgwk.CancelAync();
backgroundWaitEvent.Set();
....
backgroundWakeEvent.WaitOne(5000);
if (bkgwk.CancellationPending)
{
cancelled = true;
e.Cancel = true;
bkgwk.Dispose();
break;
}
You're going down the wrong path.
Sleep()
on any thread. Certainly not for more than a few ms. Sleep(1)
in a busy-wait for 5 seconds is a big waste of CPU. You are hurting your other threads. At the very least consider upping it to Sleep(100)
or so. Find the max delay you will allow for your Cancel. As a solution: Use a Timer. You have a periodical task, use the right tool.
Use System.Threading.Timer
for ThreadPool based background work. Update the GUI through Dispatcher.Invoke().
Use the Dispatcher.Timer
to execute small (under 0.1 sec) portions of work on the Main thread. You can directly update the GUI.