-1

I have a BackgroundWorker process created this way:

_worker = new BackgroundWorker();
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += WaitForCard;
_worker.RunWorkerAsync();

The worker process is calling an API for smart card (for instance it is SCardGetStatusChange function API). That call blocks execution until a card is placed on a reader.

The problem is when I close the Winform application. I am using:

    _worker.CancelAsync();
    _worker.Dispose();

The worker process set its CancellationPending property to true and the main form closes, however, application does not actually exit because the worker process is still waiting for the external input.

How to finish the working process even when it is waiting for an external input?

jstuardo
  • 3,901
  • 14
  • 61
  • 136
  • 2
    That is not accurate, BGW cannot prevent an app from terminating. The thread it uses has IsBackground = true. You will have to look for a deadlock reason. Probably something yucky in the smart-card device driver. – Hans Passant May 26 '17 at 00:34
  • No driver... I am using the Smart card API belonging to Windows. It is really not a problem of the smart card because the API is waiting for the presence of a card. If a card is never placed, the method does not return. So I need to force the background process to terminate. If I don't use BGW, what else can I use? Normal threads? – jstuardo May 26 '17 at 02:50
  • Short version: if your API has a good way to cancel the operation, e.g. `SCardCancel()`, then use that to cancel the operation. If it doesn't, you're stuck with several options, all of them poor. The safest approach is the "run the API in a separate process you can kill" option. It goes downhill from there (killing threads, app domains, etc.) See marked duplicates for additional info, as well as https://blogs.msdn.microsoft.com/pfxteam/2012/10/05/how-do-i-cancel-non-cancelable-async-operations/. – Peter Duniho May 26 '17 at 04:22
  • @PeterDuniho why do you think this is duplicate? the answer was in fact the SCardCancel call. That way, the BGW stops without doing other trick to force the cancellation. – jstuardo May 26 '17 at 12:16
  • It's a duplicate because your question asks broadly how to do it in general, and the card API is (in your own words) just an example. If you'd asked "how do I cancel my call to `SCardGetStatusChange()`?", that would have been a poor question (showing basically **no** research effort), but at least it would have been unique. As asked, your question absolutely is a duplicate. – Peter Duniho May 26 '17 at 16:46

1 Answers1

1

EDIT: To force the SCardGetStatusChange function to cancel, use SCardCancel: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379470(v=vs.85).aspx

Blue Goose
  • 137
  • 5
  • The problem is I cannot control the loop, because the Smart card API is waiting for the card to be placed in the reader. – jstuardo May 26 '17 at 02:45
  • @jstuardo: you shouldn't need to control the loop. You're calling the method from `BackgroundWorker.DoWork` event handler. Use a different thread to call the `SCardCancel()` method. The call to `SCardGetStatusChange()` should complete with an indication that it was canceled. – Peter Duniho May 26 '17 at 04:24