Running a collection of BackgroundWorkers one after the other

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite
1












In my project, I had three BackgroundWorkers that can be run independently, but I also wanted to allow the user to "Run All" of them, but not at the same time. They need to be run one after the other. So, I devised this class to create a Queue of BackgroundWorkers, subscribe to their RunWorkerCompleted event handler, and run the next worker in the Queue.



I would like to know:



  1. If this is even a good idea

  2. If there are any potential bugs I might have overlooked

  3. If I've violated any normal .Net conventions.

  4. Any ways to improve the functionality, speed, or readability of the code



/// <summary>
/// Simplifies running a Queue of BackgroundWorkers one after the other without blocking the current thread.
/// </summary>
public class BackgroundWorkerQueue

/// <summary>Continue running BackgroundWorkerQueue if any BackgroundWorker causes an Exception.</summary>
public bool ContinueOnError get; set;
private Queue<QueuedWorker> Queue get; set;
public BackgroundWorkerQueue( )

this.Queue = new Queue<QueuedWorker>();

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, BackgroundWorker worker )

left.Add(worker);
return left;

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, QueuedWorker worker )

left.Add(worker);
return left;

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public void Add( BackgroundWorker worker, object argument )

this.Queue.Enqueue(new QueuedWorker(worker,argument));

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
public void Add( BackgroundWorker worker )

this.Queue.Enqueue(new QueuedWorker(worker,null));

/// <summary>Add a BackgroundWorker to the Queue</summary>
public void Add( QueuedWorker worker )

this.Queue.Enqueue(worker);

/// <summary>Starts execution of the BackgroundWorkers.</summary>
public void Run( )

Debug.Print("BackgroundWorkerQueue.Run(), 0 items in queue.", this.Queue.Count);
QueuedWorker q = this.Queue.Dequeue();
q.Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.Completed);
q.Worker.RunWorkerAsync(q.Argument);

private void Completed( object sender, RunWorkerCompletedEventArgs e )

Debug.Print("BackgroundWorkerQueue.Completed()");
BackgroundWorker worker = sender as BackgroundWorker;
if( worker != null )


/// <summary>Object containing a BackgroundWorker and optional Argument to be run.</summary>
public class QueuedWorker

/// <summary></summary>A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</summary>
public object Argument get; set;
/// <summary>BackgroundWorker to be run.</summary>
public BackgroundWorker Worker get; set;
public QueuedWorker()


/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public QueuedWorker( BackgroundWorker worker, object argument )

this.Worker = worker;
this.Argument = argument;





Example Usage:



var q = new BackgroundWorkerQueue();
q.Add(InventoryBgWorker,"FIN STOCK"); // to add a worker, you can call one of the Add(...) methods
q += PartDataBgWorker; // or you can use the += operator
q += OpenOrdersBgWorker;
q.Run(); // Does not block current thread.






share|improve this question





















  • You could consider creating class that converts/wraps the background workers using TPL (Task / TaskCompletionSource) and then await the workers. Task.WhenAll can also be used to run them simultaneously.
    – Nkosi
    Jan 6 at 2:13







  • 1




    Or foregoing the background workers altogether and use Tasks blog.stephencleary.com/2013/05/… and blog.stephencleary.com/2013/09/…
    – Nkosi
    Jan 6 at 4:46

















up vote
4
down vote

favorite
1












In my project, I had three BackgroundWorkers that can be run independently, but I also wanted to allow the user to "Run All" of them, but not at the same time. They need to be run one after the other. So, I devised this class to create a Queue of BackgroundWorkers, subscribe to their RunWorkerCompleted event handler, and run the next worker in the Queue.



I would like to know:



  1. If this is even a good idea

  2. If there are any potential bugs I might have overlooked

  3. If I've violated any normal .Net conventions.

  4. Any ways to improve the functionality, speed, or readability of the code



/// <summary>
/// Simplifies running a Queue of BackgroundWorkers one after the other without blocking the current thread.
/// </summary>
public class BackgroundWorkerQueue

/// <summary>Continue running BackgroundWorkerQueue if any BackgroundWorker causes an Exception.</summary>
public bool ContinueOnError get; set;
private Queue<QueuedWorker> Queue get; set;
public BackgroundWorkerQueue( )

this.Queue = new Queue<QueuedWorker>();

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, BackgroundWorker worker )

left.Add(worker);
return left;

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, QueuedWorker worker )

left.Add(worker);
return left;

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public void Add( BackgroundWorker worker, object argument )

this.Queue.Enqueue(new QueuedWorker(worker,argument));

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
public void Add( BackgroundWorker worker )

this.Queue.Enqueue(new QueuedWorker(worker,null));

/// <summary>Add a BackgroundWorker to the Queue</summary>
public void Add( QueuedWorker worker )

this.Queue.Enqueue(worker);

/// <summary>Starts execution of the BackgroundWorkers.</summary>
public void Run( )

Debug.Print("BackgroundWorkerQueue.Run(), 0 items in queue.", this.Queue.Count);
QueuedWorker q = this.Queue.Dequeue();
q.Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.Completed);
q.Worker.RunWorkerAsync(q.Argument);

private void Completed( object sender, RunWorkerCompletedEventArgs e )

Debug.Print("BackgroundWorkerQueue.Completed()");
BackgroundWorker worker = sender as BackgroundWorker;
if( worker != null )


/// <summary>Object containing a BackgroundWorker and optional Argument to be run.</summary>
public class QueuedWorker

/// <summary></summary>A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</summary>
public object Argument get; set;
/// <summary>BackgroundWorker to be run.</summary>
public BackgroundWorker Worker get; set;
public QueuedWorker()


/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public QueuedWorker( BackgroundWorker worker, object argument )

this.Worker = worker;
this.Argument = argument;





Example Usage:



var q = new BackgroundWorkerQueue();
q.Add(InventoryBgWorker,"FIN STOCK"); // to add a worker, you can call one of the Add(...) methods
q += PartDataBgWorker; // or you can use the += operator
q += OpenOrdersBgWorker;
q.Run(); // Does not block current thread.






share|improve this question





















  • You could consider creating class that converts/wraps the background workers using TPL (Task / TaskCompletionSource) and then await the workers. Task.WhenAll can also be used to run them simultaneously.
    – Nkosi
    Jan 6 at 2:13







  • 1




    Or foregoing the background workers altogether and use Tasks blog.stephencleary.com/2013/05/… and blog.stephencleary.com/2013/09/…
    – Nkosi
    Jan 6 at 4:46













up vote
4
down vote

favorite
1









up vote
4
down vote

favorite
1






1





In my project, I had three BackgroundWorkers that can be run independently, but I also wanted to allow the user to "Run All" of them, but not at the same time. They need to be run one after the other. So, I devised this class to create a Queue of BackgroundWorkers, subscribe to their RunWorkerCompleted event handler, and run the next worker in the Queue.



I would like to know:



  1. If this is even a good idea

  2. If there are any potential bugs I might have overlooked

  3. If I've violated any normal .Net conventions.

  4. Any ways to improve the functionality, speed, or readability of the code



/// <summary>
/// Simplifies running a Queue of BackgroundWorkers one after the other without blocking the current thread.
/// </summary>
public class BackgroundWorkerQueue

/// <summary>Continue running BackgroundWorkerQueue if any BackgroundWorker causes an Exception.</summary>
public bool ContinueOnError get; set;
private Queue<QueuedWorker> Queue get; set;
public BackgroundWorkerQueue( )

this.Queue = new Queue<QueuedWorker>();

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, BackgroundWorker worker )

left.Add(worker);
return left;

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, QueuedWorker worker )

left.Add(worker);
return left;

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public void Add( BackgroundWorker worker, object argument )

this.Queue.Enqueue(new QueuedWorker(worker,argument));

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
public void Add( BackgroundWorker worker )

this.Queue.Enqueue(new QueuedWorker(worker,null));

/// <summary>Add a BackgroundWorker to the Queue</summary>
public void Add( QueuedWorker worker )

this.Queue.Enqueue(worker);

/// <summary>Starts execution of the BackgroundWorkers.</summary>
public void Run( )

Debug.Print("BackgroundWorkerQueue.Run(), 0 items in queue.", this.Queue.Count);
QueuedWorker q = this.Queue.Dequeue();
q.Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.Completed);
q.Worker.RunWorkerAsync(q.Argument);

private void Completed( object sender, RunWorkerCompletedEventArgs e )

Debug.Print("BackgroundWorkerQueue.Completed()");
BackgroundWorker worker = sender as BackgroundWorker;
if( worker != null )


/// <summary>Object containing a BackgroundWorker and optional Argument to be run.</summary>
public class QueuedWorker

/// <summary></summary>A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</summary>
public object Argument get; set;
/// <summary>BackgroundWorker to be run.</summary>
public BackgroundWorker Worker get; set;
public QueuedWorker()


/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public QueuedWorker( BackgroundWorker worker, object argument )

this.Worker = worker;
this.Argument = argument;





Example Usage:



var q = new BackgroundWorkerQueue();
q.Add(InventoryBgWorker,"FIN STOCK"); // to add a worker, you can call one of the Add(...) methods
q += PartDataBgWorker; // or you can use the += operator
q += OpenOrdersBgWorker;
q.Run(); // Does not block current thread.






share|improve this question













In my project, I had three BackgroundWorkers that can be run independently, but I also wanted to allow the user to "Run All" of them, but not at the same time. They need to be run one after the other. So, I devised this class to create a Queue of BackgroundWorkers, subscribe to their RunWorkerCompleted event handler, and run the next worker in the Queue.



I would like to know:



  1. If this is even a good idea

  2. If there are any potential bugs I might have overlooked

  3. If I've violated any normal .Net conventions.

  4. Any ways to improve the functionality, speed, or readability of the code



/// <summary>
/// Simplifies running a Queue of BackgroundWorkers one after the other without blocking the current thread.
/// </summary>
public class BackgroundWorkerQueue

/// <summary>Continue running BackgroundWorkerQueue if any BackgroundWorker causes an Exception.</summary>
public bool ContinueOnError get; set;
private Queue<QueuedWorker> Queue get; set;
public BackgroundWorkerQueue( )

this.Queue = new Queue<QueuedWorker>();

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, BackgroundWorker worker )

left.Add(worker);
return left;

public static BackgroundWorkerQueue operator +( BackgroundWorkerQueue left, QueuedWorker worker )

left.Add(worker);
return left;

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public void Add( BackgroundWorker worker, object argument )

this.Queue.Enqueue(new QueuedWorker(worker,argument));

/// <summary>Add a BackgroundWorker to the Queue</summary>
/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
public void Add( BackgroundWorker worker )

this.Queue.Enqueue(new QueuedWorker(worker,null));

/// <summary>Add a BackgroundWorker to the Queue</summary>
public void Add( QueuedWorker worker )

this.Queue.Enqueue(worker);

/// <summary>Starts execution of the BackgroundWorkers.</summary>
public void Run( )

Debug.Print("BackgroundWorkerQueue.Run(), 0 items in queue.", this.Queue.Count);
QueuedWorker q = this.Queue.Dequeue();
q.Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.Completed);
q.Worker.RunWorkerAsync(q.Argument);

private void Completed( object sender, RunWorkerCompletedEventArgs e )

Debug.Print("BackgroundWorkerQueue.Completed()");
BackgroundWorker worker = sender as BackgroundWorker;
if( worker != null )


/// <summary>Object containing a BackgroundWorker and optional Argument to be run.</summary>
public class QueuedWorker

/// <summary></summary>A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</summary>
public object Argument get; set;
/// <summary>BackgroundWorker to be run.</summary>
public BackgroundWorker Worker get; set;
public QueuedWorker()


/// <param name="worker">BackgroundWorker to call RunWorkerAsync() on.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the System.ComponentModel.BackgroundWorker.DoWork event handler.</param>
public QueuedWorker( BackgroundWorker worker, object argument )

this.Worker = worker;
this.Argument = argument;





Example Usage:



var q = new BackgroundWorkerQueue();
q.Add(InventoryBgWorker,"FIN STOCK"); // to add a worker, you can call one of the Add(...) methods
q += PartDataBgWorker; // or you can use the += operator
q += OpenOrdersBgWorker;
q.Run(); // Does not block current thread.








share|improve this question












share|improve this question




share|improve this question








edited Jan 30 at 1:15









Jamal♦

30.1k11114225




30.1k11114225









asked Jan 5 at 16:40









Drew Chapin

799719




799719











  • You could consider creating class that converts/wraps the background workers using TPL (Task / TaskCompletionSource) and then await the workers. Task.WhenAll can also be used to run them simultaneously.
    – Nkosi
    Jan 6 at 2:13







  • 1




    Or foregoing the background workers altogether and use Tasks blog.stephencleary.com/2013/05/… and blog.stephencleary.com/2013/09/…
    – Nkosi
    Jan 6 at 4:46

















  • You could consider creating class that converts/wraps the background workers using TPL (Task / TaskCompletionSource) and then await the workers. Task.WhenAll can also be used to run them simultaneously.
    – Nkosi
    Jan 6 at 2:13







  • 1




    Or foregoing the background workers altogether and use Tasks blog.stephencleary.com/2013/05/… and blog.stephencleary.com/2013/09/…
    – Nkosi
    Jan 6 at 4:46
















You could consider creating class that converts/wraps the background workers using TPL (Task / TaskCompletionSource) and then await the workers. Task.WhenAll can also be used to run them simultaneously.
– Nkosi
Jan 6 at 2:13





You could consider creating class that converts/wraps the background workers using TPL (Task / TaskCompletionSource) and then await the workers. Task.WhenAll can also be used to run them simultaneously.
– Nkosi
Jan 6 at 2:13





1




1




Or foregoing the background workers altogether and use Tasks blog.stephencleary.com/2013/05/… and blog.stephencleary.com/2013/09/…
– Nkosi
Jan 6 at 4:46





Or foregoing the background workers altogether and use Tasks blog.stephencleary.com/2013/05/… and blog.stephencleary.com/2013/09/…
– Nkosi
Jan 6 at 4:46











1 Answer
1






active

oldest

votes

















up vote
4
down vote













You can forego the background workers in favor of Tasks either via Task.Run or just async functions. They can be run independently, all at once or sequentially.



The following example takes a collection of tasks and invokes them one after the other.



//Assuming all the following return Task derived results
var tasks = new Func<Task>
() => InventoryService.GetInventoryAsync("FIN STOCK"),
() => PartsService.GetPartDataAsync(),
() => OrdersService.OpenOrderAsync()
;

Debug.Print("RunAllAsync(), 0 items in collection.", tasks.Length);
foreach (var task in tasks)
try
await task();
catch (Exception e)
if (ContinueOnError)
continue;
else
break;







share|improve this answer























    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184377%2frunning-a-collection-of-backgroundworkers-one-after-the-other%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    4
    down vote













    You can forego the background workers in favor of Tasks either via Task.Run or just async functions. They can be run independently, all at once or sequentially.



    The following example takes a collection of tasks and invokes them one after the other.



    //Assuming all the following return Task derived results
    var tasks = new Func<Task>
    () => InventoryService.GetInventoryAsync("FIN STOCK"),
    () => PartsService.GetPartDataAsync(),
    () => OrdersService.OpenOrderAsync()
    ;

    Debug.Print("RunAllAsync(), 0 items in collection.", tasks.Length);
    foreach (var task in tasks)
    try
    await task();
    catch (Exception e)
    if (ContinueOnError)
    continue;
    else
    break;







    share|improve this answer



























      up vote
      4
      down vote













      You can forego the background workers in favor of Tasks either via Task.Run or just async functions. They can be run independently, all at once or sequentially.



      The following example takes a collection of tasks and invokes them one after the other.



      //Assuming all the following return Task derived results
      var tasks = new Func<Task>
      () => InventoryService.GetInventoryAsync("FIN STOCK"),
      () => PartsService.GetPartDataAsync(),
      () => OrdersService.OpenOrderAsync()
      ;

      Debug.Print("RunAllAsync(), 0 items in collection.", tasks.Length);
      foreach (var task in tasks)
      try
      await task();
      catch (Exception e)
      if (ContinueOnError)
      continue;
      else
      break;







      share|improve this answer

























        up vote
        4
        down vote










        up vote
        4
        down vote









        You can forego the background workers in favor of Tasks either via Task.Run or just async functions. They can be run independently, all at once or sequentially.



        The following example takes a collection of tasks and invokes them one after the other.



        //Assuming all the following return Task derived results
        var tasks = new Func<Task>
        () => InventoryService.GetInventoryAsync("FIN STOCK"),
        () => PartsService.GetPartDataAsync(),
        () => OrdersService.OpenOrderAsync()
        ;

        Debug.Print("RunAllAsync(), 0 items in collection.", tasks.Length);
        foreach (var task in tasks)
        try
        await task();
        catch (Exception e)
        if (ContinueOnError)
        continue;
        else
        break;







        share|improve this answer















        You can forego the background workers in favor of Tasks either via Task.Run or just async functions. They can be run independently, all at once or sequentially.



        The following example takes a collection of tasks and invokes them one after the other.



        //Assuming all the following return Task derived results
        var tasks = new Func<Task>
        () => InventoryService.GetInventoryAsync("FIN STOCK"),
        () => PartsService.GetPartDataAsync(),
        () => OrdersService.OpenOrderAsync()
        ;

        Debug.Print("RunAllAsync(), 0 items in collection.", tasks.Length);
        foreach (var task in tasks)
        try
        await task();
        catch (Exception e)
        if (ContinueOnError)
        continue;
        else
        break;








        share|improve this answer















        share|improve this answer



        share|improve this answer








        edited Jan 29 at 19:34


























        answered Jan 6 at 4:59









        Nkosi

        1,870619




        1,870619






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184377%2frunning-a-collection-of-backgroundworkers-one-after-the-other%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Greedy Best First Search implementation in Rust

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            C++11 CLH Lock Implementation