Rushui Guan Rushui Guan - 5 months ago 59
C# Question

CancellationTokenSource.Cancel doesn't work during WPF app exit

Here is a simple async call with cancellation code snippet. The code sits in a WPF application class. If I call the Cancel method via a WPF UI Command, the async method will exit properly. However, if the Cancel is invoked during the OnExit method, nothing happens. My actual code requires OnExit call because the async method uses IO resources that should be cleaned up properly.

Any ideas?

Edit: the expected behavior is that Task.Delay method should throw the OperationCancelledException when cancel is invoked. What I want to know is why it doesn't during app exit and if there are work around to get it behaving properly.

public partial class App : Application {
protected override void OnStartup(StartupEventArgs e) {

ManualResetEvent waitHandle = new ManualResetEvent(false);
CancellationTokenSource source = new CancellationTokenSource();

public void Cancel() {

async void ListenAsync(CancellationToken token) {
try {
while (true) {
await Task.Delay(300000, token);
} catch (OperationCanceledException) {
} catch (Exception err) {
} finally {

protected override void OnExit(ExitEventArgs e) {


Found the problem.

The Cancel call during WPF App Exit is on the same synchronization context as the ListenAsync function. Because the thread is blocked by the waitHandle.WaitOne, there is no way for the ListenAsync method to resume executing on the same synchronization context.

The problem can be resolved by changing the async call to

await Task.Delay(300000, token).ConfigureAwait(false);

This allows the remainder of the ListenAsync function to stay on the sync context of the Task.Delay function.