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
});
}
}
-
\$\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– svick2014年02月08日 16:31:51 +00:00Commented Feb 8, 2014 at 16:31
-
\$\begingroup\$ Yes, the ordering is important. \$\endgroup\$Brannon– Brannon2014年02月08日 16:46:56 +00:00Commented Feb 8, 2014 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– Brannon2014年02月08日 16:51:49 +00:00Commented Feb 8, 2014 at 16:51
1 Answer 1
First, some notes about your code:
- Using
Task
s that are first created and later started usually doesn't make much sense. To represent some work to be done, just use a delegate. Task
s almost never need to beDispose
d.
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);
}
-
\$\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– Brannon2014年02月18日 18:59:17 +00:00Commented Feb 18, 2014 at 18:59