3
\$\begingroup\$

One of my classes regularly triggers one of two asynchronous operations: a "turn on" and a "turn off" that each take about a second. I'm using this method below to make sure that they don't run simultaneously. It doesn't seem very elegant to me. Is there some better way to do this? I'm using .NET 4.0, but I would like to know if there are any .NET 4.5 methods that make this easier.

private Task _changingControl;
private void RunControlTask(Task newTask)
{
    var cc = _changingControl;
    if (cc == null || cc.IsCompleted)
    {
        _changingControl = newTask;
        newTask.Start();
    }
    else
    {
        _changingControl = cc.ContinueWith(old =>
        {
            newTask.RunSynchronously();
            newTask.Dispose(); // only needed if we manually wait for it to finish
        });
    }
}
\$\endgroup\$
  • \$\begingroup\$ If you submit new tasks faster than they can be executed, is it necessary that they execute in the order they were submitted in? \$\endgroup\$ – svick Feb 8 '14 at 16:31
  • \$\begingroup\$ Yes, the ordering is important. \$\endgroup\$ – Brannon Feb 8 '14 at 16:46
  • \$\begingroup\$ At some point I would like to change it such that if I'm currently "turning off", and I have both an on and an off task waiting, I skip the following two because my current action will take me to the appropriate state. \$\endgroup\$ – Brannon Feb 8 '14 at 16:51
3
\$\begingroup\$

First, some notes about your code:

Now, I think that what you want to do would be easiest to achieve using ActionBlock from TPL Dataflow. When you want to perform the operation, you would send a message to the block and the action in the block would execute it. ActionBlock already performs all synchronization necessary to make sure only one operation executes at a time.

ActionBlock<bool> _changeControlBlock = new ActionBlock<bool>(ChangeControl);

private void ChangeControl(bool on)
{
    if (on)
    {
        // turn on
    }
    else
    {
        // turn off
    }
}

public void TurnOn()
{
    _changeControlBlock.Post(true);
}

public void TurnOn()
{
    _changeControlBlock.Post(false);
}
\$\endgroup\$
  • \$\begingroup\$ I think this sufficiently answers the question of alternative methods. I make a different post for the question of skipping tasks in the middle. \$\endgroup\$ – Brannon Feb 18 '14 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.