WinRT BackgroundWorker type


Home | Blog | Bio and Contact | CSLA .NET | CSLA Store

12 October 2011

There is no BackgroundWorker (BW) component in WinRT. Although that is arguably a good thing, I have CSLA .NET code that relies on this component. I can’t eliminate the BW from CSLA, because I need to continue to support .NET, Silverlight, and Windows Phone, even as I add support for WinRT.

Because .NET/SL/WP7 don’t (yet) have the async/await keywords, and WinRT doesn’t have BW, I need to come up with a solution that leaves existing code/behavior alone, and yet provides comparable behavior in WinRT.

To resolve this issue, I’ve created a BackgroundWorker type for WinRT. This type hasn’t gone through extensive testing, but it is a good start at least:

http://www.lhotka.net/cslacvs/viewvc.cgi/core/trunk/Source/Csla.WinRT/Threading/BackgroundWorkerBCL.cs

//-----------------------------------------------------------------------// <copyright file="BackgroundWorker.cs" company="Marimer LLC">//     Copyright (c) Marimer LLC. All rights reserved.//     Website: http://www.lhotka.net/cslanet/// </copyright>// <summary>Implementation of old BCL BackgroundWorker ported to WinRT.</summary>//-----------------------------------------------------------------------using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Windows.UI.Core;using Windows.UI.Xaml; namespace System.ComponentModel{  public class BackgroundWorker : DependencyObject  {    private CoreDispatcher _dispatcher;     public BackgroundWorker()    {      _dispatcher = this.Dispatcher;    }     public void CancelAsync()    {      if (!WorkerSupportsCancellation)        throw new NotSupportedException();      CancellationPending = true;    }     public bool CancellationPending { get; private set; }     public event ProgressChangedEventHandler ProgressChanged;     public void ReportProgress(int percentProgress)    {      ReportProgress(percentProgress, null);    }     public void ReportProgress(int percentProgress, object userState)    {      if (ProgressChanged != null)        _dispatcher.Invoke(CoreDispatcherPriority.Normal,          (sender, args) =>          {            ProgressChanged(this, new ProgressChangedEventArgs(percentProgress, userState));          },          this, null);    }     public bool WorkerReportsProgress { get; set; }    public bool WorkerSupportsCancellation { get; set; }    public bool IsBusy { get; set; }     public event DoWorkEventHandler DoWork;    public event RunWorkerCompletedEventHandler RunWorkerCompleted;    protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)    {      if (RunWorkerCompleted != null)        RunWorkerCompleted(this, e);    }     public void RunWorkerAsync()    {      RunWorkerAsync(null);    }     public async void RunWorkerAsync(object userState)    {      if (DoWork != null)      {        CancellationPending = false;        IsBusy = true;        try        {          var args = new DoWorkEventArgs { Argument = userState };          await Task.Run(() =>          {            DoWork(this, args);          });          IsBusy = false;          OnRunWorkerCompleted(new RunWorkerCompletedEventArgs { Result = args.Result });        }        catch (Exception ex)        {          IsBusy = false;          OnRunWorkerCompleted(new RunWorkerCompletedEventArgs { Error = ex });        }      }    }  }   public delegate void DoWorkEventHandler(object sender, DoWorkEventArgs e);   public class DoWorkEventArgs : EventArgs  {    public DoWorkEventArgs()    { }     public DoWorkEventArgs(object argument)    {      Argument = argument;    }     public object Argument { get; set; }    public bool Cancel { get; set; }    public object Result { get; set; }  }   public delegate void RunWorkerCompletedEventHandler(object sender, RunWorkerCompletedEventArgs e);   public class RunWorkerCompletedEventArgs : EventArgs  {    public RunWorkerCompletedEventArgs()    { }     public RunWorkerCompletedEventArgs(object result, Exception error, bool cancelled)    {      Result = result;      Error = error;      Cancelled = cancelled;    }     public Exception Error { get; set; }    public object Result { get; set; }    public bool Cancelled { get; set; }  }}