-2

I have an app that calls a third party remote server. I'm using a BackgroundWorker to run it Async.

If I call CancelAsync() to cancel the remote process, and then use the worker.CancellationPending status to trigger a call to the Close() method on this remote server, the remote server pops up a message "You are trying to close this process, is that what you want?" and Yes/No buttons.

If the user presses Yes, then no problem, remote server shuts down. But if the user presses No, then how do I cancel the CancellationPending status so that my process can continue until such time as the user calls CancelAsynch() again?

Edit: Following the first answer below: how do I deal with the fact that a user can choose not to close down the remote server and leaves it running while my app is in a state of cancellation that cannot be changed?

Edit: Before you keyboard warriors mark this as duplicate, read the damn question.

Dave Tapson
  • 810
  • 1
  • 9
  • 22
  • Take a look here : http://stackoverflow.com/q/4732737/3956100 – Niklas Sep 21 '16 at 21:09
  • _"how do I deal with the fact that a user can choose not to close down the remote server"_ -- you need to push that interaction back in your code to occur _before_ you call `CancelAsync()`. That way, you don't wind up cancelling a process that shouldn't be cancelled. Note that that will also let the processing continue while the user thinks about whether they want to cancel or not, which in most cases should be a good thing. – Peter Duniho Sep 22 '16 at 00:13
  • @Niklas That link is not the same issue. – Dave Tapson Sep 22 '16 at 04:50
  • I think I'm going to have to scrap BackgroundWorker and just use a normal method with doEvents. The UI (this version anyway) is a simple one page UI so the risks should be small. I will call the Close() method and then check to see if the com object still exists (using a try/catch?) - if doesn't exist, break loop, if it does exist, just carry on processing... – Dave Tapson Sep 22 '16 at 10:58
  • @PeterDuniho The problem is that the third party server throws the popup, not my code. I can push my interaction back but when I try and close the third party app, it will still throw the popup. The only other option would be to find a way of indicating to the BackgroundWorker that the app needs to be closed that is not by using the CancelAsync call. Not sure this can be done without crossing threads? – Dave Tapson Sep 22 '16 at 11:03
  • @DaveTapson my bad. – Niklas Sep 22 '16 at 12:07

2 Answers2

0

CancellationPending is meant to be set to true if Cancel has been requested, and not set back to false ever. That would lead to unpredictable behaviour: what if the cancellation was already observed, and what if not? In one case the operation would be cancelled nonetheless, and the other not.

Adam B
  • 324
  • 1
  • 8
  • Fair enough. So how do I deal with the fact that a user can choose not to close down the remote server and leaves it running while my app is in a state of cancellation that cannot be changed? I can set a flag to ignore the CancellationPending status but then the user can not cancel from that point on which is blech. – Dave Tapson Sep 21 '16 at 20:59
  • @DaveTapson do you have access to .Net Framework 4.5 ? – Niklas Sep 21 '16 at 21:05
0

As a general rule, you should not have user interaction inside the BackgroundWorker logic. (It is called BackgroundWorker for a reason).

Remember that the CancelAsync() is asynchronous, so if you do ask for user interaction during calculation, the MessageBox might pop up a few seconds/minutes later when the user is doing something completely different.

If you properly isolate the threads, you shouldn't have this kind of problems.

You should ask for user confirmation before you call CancelAsync() ?

User asks for cancelation -> You ask for confirmation -> call CancelAsync()

Fabio Marreco
  • 2,186
  • 2
  • 23
  • 24
  • the remote sever is a third party app. I didn't put the check there, the developer of the app did. – Dave Tapson Sep 22 '16 at 04:45
  • Since you are not in full control of the cancellation process, maybe you can avoid using `CancelAsync`? Just call `Close()` directly from the UI thread ? Or is this service not thread-safe ? (If that is the case, you can create a bool variable `_cancellationPending`, set it to true on the close button, and avoid the `CancelAsync` altogether.) – Fabio Marreco Oct 25 '16 at 11:25