Reputation: 6265
I want to chain Task
s, then start the chain in parallel.
This snippet is just to illustrate my question:
var taskOrig = new Task(() => { });
var task = taskOrig;
foreach (var msg in messages)
{
task=task.ContinueWith(t => Console.WriteLine(msg));
}
taskOrig.Start();
Everything works fine except a little perfectionist inside me doesn't like having empty method executed first () => { }
.
Is there any way to avoid it?
I do understand It's barely affecting performance (unless you do it really often), but still. Performance matters in my case, so checking if task exists in every iteration is not the way to do it.
Upvotes: 6
Views: 2077
Reputation: 50712
One way to do that, is to create task in loop if it is null, but the code you provide looks better for me:
Task task = null;
foreach (var msg in messages)
{
if (task == null)
task = new Task(() => Console.WriteLine(msg))
else
task = task.ContinueWith(t => Console.WriteLine(msg));
}
task.Start();
Upvotes: 2
Reputation: 203820
You could do this:
Task task = Task.FromResult<object>(null);
foreach (var msg in messages)
{
task = task.ContinueWith(t => Console.WriteLine(msg));
}
The previous solution won't work in 4.0. In 4.0 you'd need to do the following instead:
var tcs = new TaskCompletionSource<object>();
Task task = tcs.Task;
foreach (var msg in messages)
{
task = task.ContinueWith(t => Console.WriteLine(msg));
}
tcs.SetResult(null);
(You can move SetResult
to before the foreach loop if you prefer.)
Technically it's not the same as the continuations will start executing while you're still adding more. That's unlikely to be a problem though.
Another option would be to use something like this:
public static Task ForEachAsync<T>(IEnumerable<T> items, Action<T> action)
{
return Task.Factory.StartNew(() =>
{
foreach (T item in items)
{
action(item);
}
});
}
An example usage would be:
ForEachAsync(messages, msg => Console.WriteLine(msg));
Upvotes: 3
Reputation: 5825
Perhaps this:
if(messages.Length > 0)
{
Task task = new Task(t => Console.WriteLine(messages[0]));
for(int i = 1; i < messages.Length; i++)
{
task = task.ContinueWith(t => Console.WriteLine(messages[i]));
}
task.Start();
}
Upvotes: 1