Created
July 10, 2018 08:22
-
-
Save JimBobSquarePants/ec7e267b797451271747efd87b5e80ac to your computer and use it in GitHub Desktop.
Attempt at demoing returning only completed tasks from a collection.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
namespace TaskTest | |
{ | |
class Program | |
{ | |
private static Random r = new Random(); | |
static async Task Main(string[] args) | |
{ | |
var tasks = new Task<IEnumerable<int>>[] { ExternalTask(), ExternalTask(), ExternalTask(), ExternalTask(), ExternalTask() }; | |
var t2 = await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(3000)); | |
var completedResults = tasks | |
.Where(t => t.Status == TaskStatus.RanToCompletion) | |
.Select(t => t.Result) | |
.ToList(); | |
foreach (var item in completedResults) | |
{ | |
Console.WriteLine($"Task completed with {item.First()} delay."); | |
} | |
Console.ReadLine(); | |
} | |
private static Task<IEnumerable<int>> ExternalTask() | |
{ | |
int delay = r.Next(0, 6000); | |
Task.Delay(delay); | |
var enumerable = Enumerable.Repeat(delay, 6); | |
return Task.FromResult(enumerable); | |
} | |
} | |
} |
Await Task.Delay: ExternalTask is running synchronously. It kicks off a task delay but doesn't await on it.
You could replace that with a Thread.Sleep
instead or make the method async
and await on Task.Delay
. Obviously in production apps Thread.Sleep
would get Ben Adams to come after you.
Complete working demo. await
all the things!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace TaskDemo
{
class Program
{
private static Random r = new Random();
private const int delay = 3000;
static async Task Main(string[] args)
{
var tasks = new Task<IEnumerable<int>>[] { ExternalTask(), ExternalTask(), ExternalTask(), ExternalTask(), ExternalTask() };
// Gather the results that complete within the timespan interval.
var completedResults = await WhenAll(tasks, TimeSpan.FromMilliseconds(3000));
Console.WriteLine($"Completed Tasks within {delay}:");
foreach (var item in completedResults)
{
Console.WriteLine($"Task completed with {item.First()} milliseconds delay.");
}
Console.ReadLine();
}
private async static Task<IEnumerable<int>> ExternalTask()
{
// Randomly delay the task to anywhere between 0 and 2x the delay
int milliseconds = r.Next(0, 2 * delay);
Console.WriteLine($"Task will take {milliseconds} milliseconds.");
await Task.Delay(milliseconds);
var enumerable = Enumerable.Repeat(milliseconds, 6);
return enumerable;
}
/// <summary>
/// Creates a task that will complete when <see cref="Task{TResult[]}"/> the timeout interval has passed.
/// </summary>
/// <typeparam name="TResult">The type of result.</typeparam>
/// <param name="tasks">The enumerable of tasks to attempt to complete.</param>
/// <param name="timeout">The timeout.</param>
/// <returns>The <paramref name="tasks"/> completed within the timespan limit.</returns>
private static async Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks, TimeSpan timeout)
{
await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(timeout));
return tasks
.Where(t => t.Status == TaskStatus.RanToCompletion)
.Select(t => t.Result)
.ToArray();
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The above doesn't do what I expected.
I assumed that the the
completedResults
enumerable would only contain a subset of thetasks
enumerable since some will run for longer than theTask.Delay(3000)
task but it's returning all of them.What have I done wrong?