BitsManager - Calling EnumJobs() and Dispose() seems to dispose of jobs it doesn't own

Feb 23, 2016 at 3:34 PM

By default when you create a BitsManager object the internal job dictionary (BitsJobs) is empty and you only get a BitsJob added to it when you call CreateJob(). But when you call EnumJobs() this then retrieves all the Jobs for the current user and then adds/updates the job dictionary (BitsJobs).

Now when you call Dispose() on the BitsManager it disposes of all the jobs in the dictionary, so potentially ones which weren't created through the instance of BitsManager you are calling Dispose() on.

The problem I see is if you have multiple BitsManager running on different threads. If EnumJobs() has been called and then Dispose() it causes problems for other instances of BitsManager as the Jobs they potentially created have been disposed. One symptom I see of this is that the callbacks to the BitsManager stop for its own jobs.

So the question is should EnumJobs() just return a new BitsJob dictionary and not update it's own internal dictionary as this will prevent the issue with it disposing jobs it doesn't really own?

Feb 23, 2016 at 4:16 PM
Actually looking into my specific problem further (callbacks stop working). I think the issue is when calling EnumJobs in that as it builds the new BitsJobs dictionary it creates new BitsJob objects. Now when these are created the NotificationInterface (callbacks) is pointed at the BitsManager which EnumJobs is called on. So the original BitsManager which created the job stops receiving the callbacks. It seems BITS has a limitation in that a BITS job can only have one subscriber (unlike events in .Net).

So it seems you can't have many BitsManager instances where they all receive an update for the same set of jobs. It will only be the last instance which called EnumJobs that will receive the updates. Although saying this if that BitsManager instance is disposed it seems to restore the original callback handler so the original BitsManager might get the update if the job hasn't finished.