How to cancel an asynchronous call? The .NET APM doesn't seem to support this operation.
I have the following loop in my code which spawns multiple threads on the ThreadPool. When I click a button on my UI, I would like these threads (or asynchronous calls) to end.
foreach (var sku in skus)
{
loadSku.BeginInvoke(...
}
Is there any elegant solution other than creating a global "Cancel flag" and having the asynchronous methods to look for it?
A "cancel flag" is the way to do it, though not a global one, necessarily. The unavoidable point is that you need some way to signal to the thread that it should stop what it's doing.
In the case of BeginInvoke, this is hard to do with anything but a global flag, because the work is carried out on the threadpool, and you don't know which thread. You have a couple of options (in order of preference):
Use the BackgroundWorker instead of BeginInvoke. This has cancellation functionality baked-in. This has other benefits, like progress monitoring, and "Work complete" callbacks. It also nicely handles exceptions.
Use ThreadPool.QueueUserWorkItem, passing in an object as the state that has a Cancel() method that sets a Cancelled flag that the executing code can check. Of course you'll need to keep a reference to the state object so you can call Cancel() on it (which is something the BackgroundWorker does for you - you have a component on your form. (Thanks to Fredrik for reminding about this).
Create your own ThreadStart delegate, passing in a state object as with option 2.
If you're lookin for a "TerminateAsnyc" method, you won't find one. Therefore, no, there's probably no elegant way while using Control.BeginInvoke/EndInvoke. Thus, I'd put the boolean flag on the UI thread and have the delegate being executed asynchronously check that flag periodically while it's executing.
However, you might check into using background worker threads.
There are definitely other solutions, although I don't know that I would call them "elegant".
you could call Abort or Interrupt on the thread but these can have some negative side effects. Personally, for something like this I prefer to use BackgroundWorker if possible. It has a Cancel feature but it is similar to what you mentioned - a bool flag in the class that you have to periodically check for in the executing code (at least it's not a global flag). This post on stopping threads in .NET is a bit old but goes over some of the pitfalls of the other options I mentioned above.
Related
I've been wondering is there any way in which we can move BackgroundWorker to sleep and resume it again just like thread. I've searched in many forums in vain. None of them show any method which would do that. I checked Microsoft documentation and found out there isn't any predefined methods.
I know the workarounds by using resetEvents. Just asking for any other possible and much easier way.
If you use Task instead of BackgroundWorker you can use the PauseTokenSource.
This class is similar to the built in CancellationTokenSource only suitable for pausing tasks and not canceling them.
PauseTokenSource API was built exactly for what you need and it's API can replace your usage of Thread.Sleep and all the signaling events.
Other option besides PauseTokenSource can use AsyncManualResetEvent, the mechanism internal is quite similar but they differ in the API. I think that PauseTokenSource is much more convenient and especially built for this purpose, more info here.
From within your DoWork handler, you can call Thread.Sleep() whenever you want. If you want, from the GUI, to be able to signal the worker to pause, set up a concurrent queue, feed your sleep requests into it from the GUI thread, and have your DoWork handler check the queue periodically, pausing as requested.
(If you want to pause the BackgroundWorker until signaled again rather than for a certain period of time, you can do that in a similar way--just periodically check the queue for a "restart" command and sleep a few milliseconds before checking again.)
How InvokeRequired and Invoke let us make our apps thread safe.
Let's consider such code:
private void ThreadSafeUpdate(string message)
{
if (this.textBoxSome.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(msg);
this.Invoke
(d, new object[] { message });
}
else
{
// It's on the same thread, no need for Invoke
this.textBoxSome.Text = message;
}
}
Is it possible to change state of InvokeRequired after InvokeRequired and before Invoke? If not, then why?
How does Invoking make it thread safe?
If InvokeRequired illustrate is current thread owning control, how would the thread know that it is or it is not the owner.
Let's consider that SomeMethod() is currently running on Thread1. We would like to call it from Thread2. Internally this method updates some field. Does Method.Invoke contain some kind of lock mechanism internally?
What if SomeMethod() takes very long time and we would like to run something other on the control owner thread. Does Invoking lock the owner thread or is it some kind of a background thread safe task?
ThreadSafeUpdate() //takes 5 minutes in Thread2
ThreadSafeUpdate() //after 2 minutes, we are running it in other thread2
ThreadSafeUpdate() //next run from Thread3
I think it is some kind of general pattern which can be implemented outside of winforms, what's its name?
Is it possible to change state of InvokeRequired
Yes, and it is a pretty common occurrence. Either because you started the thread too soon, before the form's Load event fired. Or because the user closed the window just as this code is running. In both cases this code fails with an exception. InvokeRequired fails when the thread races ahead of the window creation, the invoked code fails when the UI thread races ahead of the thread. The odds for an exception are low, too low to ever diagnose the bug when you test the code.
How Invoking make it thread safe?
You cannot make it safe with this code, it is a fundamental race. It must be made safe by interlocking the closing of the window with the thread execution. You must make sure that the thread stopped before allowing the window to close. The subject of this answer.
how would he know that he is or he is not owner.
This is something that can be discovered with a winapi call, GetWindowsThreadProcessId(). The Handle property is the fundamental oracle for that. Pretty decent test, but with the obvious flaw that it cannot work when the Handle is no longer valid. Using an oracle in general is unwise, you should always know when code runs on a worker thread. Such code is very fundamentally different from code that runs on the UI thread. It is slow code.
We would like to call it from Thread2
This is not in general possible. Marshaling a call from one thread to a specific other thread requires that other thread to co-operate. It must solve the producer-consumer problem. Take a look at the link, the fundamental solution to that problem is a dispatcher loop. You probably recognize it, that's how the UI thread of a program operates. Which must solve this problem, it gets notifications from arbitrary other threads and UI is never thread-safe. But worker threads in general don't try to solve this problem themselves, unless you write it explicitly, you need a thread-safe Queue and a loop that empties it.
What's if SomeMethod() takes very long time
Not sure I follow, the point of using threads is to let code that takes a long time not do anything to harm the responsiveness of the user interface.
I think it is some kind of general pattern
There is, it doesn't look like this. This kind of code tends to be written when you have an oh-shoot moment and discover that your UI is freezing. Bolting threading on top of code that was never designed to support threading is forever a bad idea. You'll overlook too many nasty little details. Very important to minimize the number of times the worker thread interacts with the UI thread, your code is doing the opposite. Fall in the pit of success with the BackgroundWorker class, its RunWorkerCompleted event gives a good synchronized way to update UI with the result of the background operation. And if you like Tasks then the TaskScheduler.FromCurrentSynchronizationContext() method helps you localize the interactions.
Usually, no. But it could happen if you're using await between the InvokeRequired check and Invoke call without capturing the execution context. Of course, if you're already using await, you're probably not going to be using Invoke and InvokeRequired.
EDIT: I just noticed that InvokeRequired will return false when the control handle hasn't been created yet. It shouldn't make much of a difference, because your call will fail anyway when the control hasn't quite been created yet, but it is something to keep in mind.
It doesn't make it thread-safe. It just adds the request to the control's queue, so that it's executed the next available time on the same thread the control was created on. This has more to do with windows architecture than with general thread-safety. The end result, however, is that the code runs on a single thread - of course, this still means you need to handle shared state synchronization manually, if any.
Well, it's complicated. But in the end, it boils down to comparing the thread ID of the thread that created the control, and the current thread ID. Internally, this calls the native method GetWindowThreadProcessId - the operating system keeps track of the controls (and more importantly, their message loops).
Invoke cannot return until the GUI thread returns to its message loop. Invoke itself only posts the command to the queue and waits for it to be processed. But the command is run on the GUI thread, not the Invoke-caller. So the SomeMethod calls in your example will be serialized, and the Invoke call itself will wait until the second call finishes.
This should already be answered. The key point is "only run GUI code on the GUI thread". That's how you get reliable and responsive GUI at all times.
You can use it anywhere you've got a loop or a wait on some queue. It probably isn't all that useful, although I have actually used it already a few times (mostly in legacy code).
However, all of this is just a simple explanation of the workings. The truth is, you shouldn't really need InvokeRequired... well, ever. It's an artifact of a different age. This is really mostly about juggling threads with little order, which isn't exactly a good practice. The uses I've seen are either lazy coding, or hotfixes for legacy code - using this in new code is silly. The argument for using InvokeRequired is usually like "it allows us to handle this business logic safely whether it runs in the GUI thread or not". Hopefully, you can see the problem with that logic :)
Also, it's not free thread-safety. It does introduce delays (especially when the GUI thread is also doing some work that isn't GUI - very likely in code that uses InvokeRequired in the first place). It does not protect you from accesses to the shared state from other threads. It can introduce deadlocks. And don't even get me started on doing anything with code that uses Application.DoEvents.
And of course, it's even less useful once you take await into consideration - writing asynchronous code is vastly easier, and it allows you to make sure the GUI code always runs in the GUI context, and the rest can run wherever you want (if it uses a thread at all).
In the asynchronous programming model, there looks to be 4 ways (As stated in Calling Synchronous Methods Asynchronously) for making asynchronous method calls.
Calling the EndInvoke() method makes the calling thread wait for the method completion and returns the result.
Going through the IAsyncResult.AsyncWaitHandle.WaitOne() also seem to do the same. AsyncWaitHandle gets a signal of completion (In other word the main thread waits for the Asynchronous method's completion). Then we can execute EndInvoke() to get the result.
What is the difference between calling the EndInvoke() directly and calling it after WaitOne()/WaitAll()?
In the polling technique we provide time for other threads to utilize the system resources by calling Thread.Sleep().
Does AsyncWaitHandle.WaitOne() or EndInvoke() make the main thread go on sleep while waiting?
Q1. There is no difference in the way your code runs or your application, but there might be some runtime differences (again not sure, but a guess based my understanding of Async delegates).
IAsyncResult.AsyncWaitHandle is provided mainly as a synchronization mechanism while using WaitAll() or WaitAny() if you dont have this synchronization need you shouldn't read AsyncWaitHandle property. Reason : AsyncWaitHandle doesnt have to be implemented (created) by the delegate while running asynchronously, until it is read by the external code. I'm not sure of the way CLR handles the Async delegates and whether it creates a WaitHandler or not, but ideally if it can handle running your async delegates without creating another WaitHandle it will not, but your call to WaitOne() would create this handle and you have extra responsibility of disposing(close) it for efficient resource release. Therefore recommendation would be when there is no sycnchronization requirement which can be supported with WaitAll() or WaitAny() dont read this property.
Q2. This Question answers the difference between Sleep and Wait.
Simple things first. For your second question, yes, WaitOne and EndInvoke does indeed make the current thread sleep while waiting.
For your first questions, I can immediately identify 2 differences.
Using WaitOne requires the wait handle to be released, while using EndInvoke directly doesn't require any cleanup.
In return, using WaitOne allows for something to be done before EndInvoke, but after the task has been completed.
As for what that "something" might be, I don't really know. I suspect allocating resources to receive the output might be something that would need to be done before EndInvoke. If you really have no reason to do something at that moment, try not to bother yourself with WaitOne.
You can pass a timeout to WaitOne, so you could, for instance want to perform some other activities on a regular basis whilst waiting for the operation to complete:
do {
//Something else
) while (!waitHandle.WaitOne(100))
Would do something every ~100 milliseconds (+ whatever the something else time is), until the operation completed.
I am using ThreadPool in .NET to make some web request in the background, and I want to have a "Stop" button to cancel all the threads even if they are in the middle of making a request, so a simple bool wont do the job.
How can I do that?
Your situation is pretty much the canonical use-case for the Cancellation model in the .NET framework.
The idea is that you create a CancellationToken object and make it available to the operation that you might want to cancel. Your operation occasionally checks the token's IsCancellationRequested property, or calls ThrowIfCancellationRequested.
You can create a CancellationToken, and request cancellation through it, by using the CancellationTokenSource class.
This cancellation model integrates nicely with the .NET Task Parallel Library, and is pretty lightweight, more so than using system objects such as ManualResetEvent (though that is a perfectly valid solution too).
The correct way to handle this is to have a flag object that you signal.
The code running in those threads needs to check that flag periodically to see if it should exit.
For instance, a ManualResetEvent object is suitable for this.
You could then ask the threads to exit like this:
evt.Set();
and inside the threads you would check for it like this:
if (evt.WaitOne(0))
return; // or otherwise exit the thread
Secondly, since you're using the thread pool, what happens is that all the items you've queued up will still be processed, but if you add the if-statement above to the very start of the thread method, it will exit immediately. If that is not good enough you should build your own system using normal threads, that way you have complete control.
Oh, and just to make sure, do not use Thread.Abort. Ask the threads to exit nicely, do not outright kill them.
If you are going to stop/cancel something processing in another thread, ThreadPool is not the best choice, you should use Thread instead, and manage all of them in a container(e.g. a global List<Thread>), that guarantees you have full control of all the threads.
How do you design a method/class that should support cancellation of the operation?
I realized that I never do that in a consistent manner and I want to change that.
Some of the things I have used:
a boolean property on the class IsCancelled that I synchronize internally. sometimes I have a CanCancel property if the operation cannot be canceled at any given time
pass a Func< bool > delegate that I repeatedly call to see if the operation has been canceled.
terminate the thread manually - although this is definitely bad practise
How do you normally do that?
I would go for the CancellationTokenSource and using its associated CancellationToken
as a means for signalling cancellation. This is new in .Net Framework v4.
The concept is that the CancellationTokenSource simply calls Cancel and your code can share CancellationTokens on which you regular inspect the IsCancellationRequested property in it. This should especially be the case in tight loops or longer running operations, so as to allow your code to stop in a timely fashion.
The added bonus is that even blocked threads blocked due to a wait on a SemaphoreSlim, ManualResetEventSlim can be signalled to gracefully exit, since these classes accept a CancellationToken in their Wait method in .Net Framework v4
For example have a look at: ManualResetEventSlim.Wait that has overloads accepting a CancellationToken.
I'd prefer to use the IsCancelled property idea. Your background thread method can check it at the appropriate times, do any cleanup as needed, and terminate the operation. If you're using a callback method when the thread finishes, it's easy to check the property and see if it's valid or not. I've used framework worker thread classes that used this strategy in the past, and it's worked well.
Go back to the use case: what is the behavior you're trying to provide? If you have an asynchronous operation that you want to cancel, then you probably can best implement a method that lets you notify the other threadt via a flag or a semaphore. Sending a signal is a nice method to get it's attention, although I haven't looked into C#'s handling of signals. If you need to be able to cancel and undo, the Command pattern comes in handy.