Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Async BackgroundTaskManager and ObservableCollection

0.00/5 (No votes)
14 Dec 2010 1  
Async BackgroundTaskManager and ObservableCollection

AsyncBackgroundTaskManager and AsyncObservableCollection is a BackgroundTaskManager/ObservableCollection that supports a list and runs asynchronously.

Introduction

Cinch included a class named BackgroundTaskManager, which offloads CPU hogging work from UI thread, and notifies the UI when a work is completed.

BackgroundTaskManager uses BackgroundWorker to do the tricks, but it is easier to use:

BackgroundTaskManager<string> _bgWorker = new BackgroundTaskManager<string>(
  () => { return CPUHoggingWork(); }
  (result) => { Result = result; }
);

The advantage of using BackgroundTaskManager is that you can write all related code in one place, and you won’t mis-write UI updating code in non-UI thread (and vice versa).

BackgroundTaskManager worked for me in most cases except when I wanted to use it to return a list of items, BackgroundTaskManager only allows return all items when the computation is completed, but I wanted it to return an item as soon as it’s constructed. So the result is AsyncBackgroundTaskManager, a BackgroundTaskManager that supports async tasks.

Although ObservableCollection has a constructor that takes IEnumerable<T>, it still blocks the thread when it’s loading, so after I completed the AsyncBackgroundTaskManager, I derived a new ObservableCollection class, named AsyncObservableCollection, which uses AsyncBackgroundTaskManager to populate its items in a separated thread.

How to Use?

The constructor of AsyncBackgroundTaskManager takes a couple parameters:

  • taskFunc (Func<IEnumerable<T>>) or taskEnumerable (IEnumerable<T>) - Specify what to return here, you can use linq or a method that returns IEnumerable<T>.
  • newItemAction (Action<T>) – Runs in UI Thread when a new item is prepared.
  • removeItemAction (Action<T>) – Optional, Runs in UI Thread when an item should be removed.
  • completeAction (Action<IList<T>>) – Runs in UI Thread when taskFunc is completed.
_bgWorker2 = new AsyncBackgroundTaskManager<StringModel>(DispatcherPriority.SystemIdle,
    from fi in new DirectoryInfo(_path).EnumerateFiles("*", SearchOption.AllDirectories)
        select new StringModel(fi.FullName),
    (model) => { InternalCollection.Add(model); },
    (model) => { InternalCollection.Remove(model); },
    (modelList) => { _aborted = (modelList == null); });
_bgWorker2.RunBackgroundTask();

The constructor of AsyncObservableCollection takes similar parameters, taskFunc and completeAction:

_internalCollection2 = new AsyncObservableCollection<StringModel>(
    from fi in new DirectoryInfo(_path).EnumerateFiles("*", SearchOption.AllDirectories)
    select new StringModel(fi.FullName),
    (modelList) => { Debug.WriteLine(modelList.Count.ToString() + " polled."); }
);
_internalCollection2.Load(false);

How It Works?

There are only 158 lines in the AsyncBackgroundTaskManager class, so you won't find any magic there.

The code below appears many times. It alerts the UI thread when the collection should be changed.

_dispatcher.Invoke(_priority, new ThreadStart(() =>
           {
               //Do something
           }));

So compared with BackgroundTaskManager, instead of using BackgroundWorker, it creates a new Thread to invoke TaskFunc, then loop the IEnumerator for items. Then for each item returned, it alerts the UI Thread using NewItemAction.

Further Improvements

Performance is affected because it invokes the UI thread every time when a new item is returned, this can be avoided if I change the component so instead of pushing new item to UI thread, the UI thread creates a DispatcherTimer to pull new items when it has time.

Reference

This article has been posted on . You can find a list of my articles here.


License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here