Rachel Rachel - 1 year ago 56
C# Question

How can I wait for my async operations to finish when the application gets exited using?

If a user performs an operation, such as deleting items, it removes them from the UI right away and then deletes them from the database on a background thread using TPL. The problem is if the user exits the application before the background thread finishes, the item never actually gets deleted.

Is there a standard way of waiting for async operations to finish before shutting down the application?

My async calls look like this:

if (MyObjectList.Contains(obj)) MyObjectList.Remove(obj);
Task.Factory.StartNew(() => DAL<MyEntities>.DeleteObject(obj));


Here's the final code I went with. I'm quite happy to see it works as it should, although let me know if I can improve it. I still have a lot to learn :)

public partial class App : Application
private List<Task> _backgroundTasks = new List<Task>();

public App()
EventSystem.Subscribe<TaskStartedMessage>((e) =>

EventSystem.Subscribe<TaskEndedMessage>((e) =>
if (_backgroundTasks.Contains(e.Task))

protected override void OnExit(ExitEventArgs e)
Task.WaitAll(_backgroundTasks.Where(p => !p.IsCompleted).ToArray(), 30000);


And when starting an important background task, I'm using this syntax:

var task = Task.Factory.StartNew(() => DAL<MyEntities>.DeleteObject(obj));
EventSystem.Publish<TaskStartedMessage>(new TaskStartedMessage(task));
await task;
EventSystem.Publish<TaskEndedMessage>(new TaskEndedMessage(task));

I'm using AsyncCTP for
, and Microsoft Prism's
for the event system.

Answer Source

There is no standard way but since you create a specific Task here it should be easy to put that in a List and build some Exit-logic to Wait for all Tasks in that List.

OK, a sample. Untested and incomplete:

// untested
static class CriticalTasks
    static HashSet<Task> tasks = new HashSet<Task>();
    static object locker = new object();

    // when starting a Task
    public static void Add(Task t)

    // When a Tasks completes
    public static void Remove(Task t)

    // Having to call Remove() is not so convenient, this is a blunt solution. 
    // call it regularly
    public static void Cleanup()
           tasks.RemoveWhere(t => t.Status != TaskStatus.Running);

    // from Application.Exit() or similar. 
    public static void WaitOnExit()
        // filter, I'm not sure if Wait() on a canceled|completed Task would be OK
        var waitfor = tasks.Where(t => t.Status == TaskStatus.Running).ToArray();
        Task.WaitAll(waitfor, 5000);

The drawback is that you will have to extend each Task with the code to Add & Remove it.

Forgetting a Remove() (eg when an Exception happens) would be a (small) memory-leak. It is not too critical, instead of burdening your code with using() blocks you could also periodically run a Cleanup() method that uses HashSet.RemoveWhere() to remove non-running tasks.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download