October 7, 2008

BackgroundWorker Usage

Better Sample BackgroundWorker usage Create a class that derives from the BackgroundWorker class that implements the threading routine by overriding the OnDoWork method rather than implementing the work method using the 'DoWork' event. The class user only needs to hook up the 'ProgressChanged' and 'RunWorkerThread' completed events. This style is more object orientated than the conventional usage where the worker code is specified in the 'DoWork' event. All the routines executed on the background thread can be separated from the rest of the code and encapsulated in the worker class. This makes it easier to see what shared data the threading routine is accessing.
// This sample deletes all the 'bin' and 'obj' directories 
// under a specified directory
internal class CleanDirWorker : BackgroundWorker
{
    string m_TargetDirectory = string.Empty;

    float total = 0;
    float count = 0;


    public CleanDirWorker() :
        base()
    {
        this.WorkerReportsProgress = true;
    }

    public string TargetDirectory
    {
        get { return m_TargetDirectory; }
        set { m_TargetDirectory = value; }
    }

    private void CleanDirectories(string dirTarget)
    {
        if (Directory.Exists(dirTarget))
        {
            DirectoryInfo diTarg = new DirectoryInfo(dirTarget);
            DirectoryClean(diTarg);
        }
        else
        {
            string msg = "Directory \'" + dirTarget + "\' does not exist";
        }
    }

    private void DirectoryClean(DirectoryInfo diTarg)
    {
        DirectoryInfo[] binDirs = diTarg.GetDirectories("bin", 
    SearchOption.AllDirectories);
        DirectoryInfo[] objDirs = diTarg.GetDirectories("obj", 
    SearchOption.AllDirectories);
        total = binDirs.Length + objDirs.Length;
        this.ReportProgress(10);
        DeleteDirs(binDirs);
        DeleteDirs(objDirs);
    }

    private void DeleteDirs(DirectoryInfo[] dis)
    {
        foreach (DirectoryInfo di in dis)
        {
            try
            {
                Debug.WriteLine("Deleting \'" + di.FullName + "\'");
                //di.Delete(true);
                count = count + 1.0f;
                int progress = 10 + (int)Math.Round(0.9f * total / (total - count));
                this.ReportProgress(progress);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception occured trying to delete \'" + 
    di.FullName + "\' :" + ex.ToString());
            }
        }
    }

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        try
        {
            if (!string.IsNullOrEmpty(m_TargetDirectory))
            {
                //DirectoryCleaner dc = new DirectoryCleaner();
                CleanDirectories(m_TargetDirectory);
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine("Exception occured :" + ex.ToString());
        }
    }
}
To use it we use the events to monitor the progress of the worker thread and to find out when the worker thread has completed
// NOTE pbClean is a progress bar in this sample 

private void button_Click(object sender, RoutedEventArgs e)
{
    if (!string.IsNullOrEmpty(tbCleanTarg.Text))
    {
        AsyncCleanDirectories();
    }
}

#region CleanDirWorker Usage
CleanDirWorker m_CleanDirWorker = null;

private void InitializeCleanWorkerDir()
{
    m_CleanDirWorker = new CleanDirWorker()
    m_CleanDirWorker.RunWorkerCompleted += new
         RunWorkerCompletedEventHandler(m_CleanDirWorker_RunWorkerCompleted);
    m_CleanDirWorker.ProgressChanged += 
      new ProgressChangedEventHandler(m_CleanDirWorker_ProgressChanged);
}

private void TerminateCleanWorkerDir()
{
 m_CleanDirWorker.Dispose();
}

private void AsyncCleanDirectories()
{
    if (m_CleanDirWorker == null)
    {
 InitializeCleanWorkerDir();
        pbClean.Value = 0;
        m_CleanDirWorker.TargetDirectory = tbCleanTarg.Text;
        m_CleanDirWorker.RunWorkerAsync(null);
    }
}

void m_CleanDirWorker_ProgressChanged(
  object sender, 
  ProgressChangedEventArgs e)
{
    pbClean.Value = e.ProgressPercentage;
}

private void m_CleanDirWorker_RunWorkerCompleted(
  object sender,
  RunWorkerCompletedEventArgs e)
{
    TerminateCleanWorkerDir();
}
#endregion CleanDirWorker Usage

No comments: