Permalink
Browse files

TaskSample - refactor FirstAsync (extract MatchFunc class)

  • Loading branch information...
bobbymcr committed May 23, 2018
1 parent 27d8429 commit 5cf6cb4f93657ee6d1c5756f3072a4dd25b0d677
Showing with 54 additions and 26 deletions.
  1. +54 −26 projects/TaskSample/TaskSample.Core/Extensions/FuncTaskExtensions.cs
@@ -14,46 +14,74 @@ public static class FuncTaskExtensions
public static async Task<T> FirstAsync<T>(this IEnumerable<Func<CancellationToken, Task<T>>> funcs, Predicate<T> pred)
{
var tasks = new List<Task<T>>();
Tuple<T> firstResult = null;
using (CancellationTokenSource cts = new CancellationTokenSource())
using (MatchFunc<T> match = new MatchFunc<T>(pred))
{
foreach (Func<CancellationToken, Task<T>> func in funcs)
{
if (cts.IsCancellationRequested)
if (match.Canceled)
{
break;
}
Func<CancellationToken, Task<T>> match = async t =>
{
T result = default(T);
try
{
result = await func(t);
if (pred(result))
{
firstResult = Tuple.Create(result);
cts.Cancel();
}
}
catch (Exception)
{
}
return result;
};
Task<T> task = match(cts.Token);
Task<T> task = match.RunAsync(func);
tasks.Add(task);
}
await Task.WhenAll(tasks);
if (firstResult == null)
return match.Result;
}
}
private sealed class MatchFunc<T> : IDisposable
{
private readonly CancellationTokenSource cts;
private readonly Predicate<T> pred;
private volatile Tuple<T> firstResult;
public MatchFunc(Predicate<T> pred)
{
this.cts = new CancellationTokenSource();
this.pred = pred;
}
public bool Canceled => this.cts.IsCancellationRequested;
public T Result
{
get
{
throw new InvalidOperationException("No matching result.");
if (this.firstResult == null)
{
throw new InvalidOperationException("No matching result.");
}
return this.firstResult.Item1;
}
}
return firstResult.Item1;
public async Task<T> RunAsync(Func<CancellationToken, Task<T>> func)
{
T result = default(T);
try
{
result = await func(this.cts.Token);
if (this.pred(result))
{
this.firstResult = Tuple.Create(result);
this.cts.Cancel();
}
}
catch (Exception)
{
}
return result;
}
public void Dispose()
{
this.cts.Dispose();
}
}
}

0 comments on commit 5cf6cb4

Please sign in to comment.