English 中文(简体)
How to cancel an asynchronous call?
原标题:

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):

  1. 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.
  2. 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).
  3. 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.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签