Last active
August 29, 2015 14:25
-
-
Save emadb/50f859df510c3f9d528d to your computer and use it in GitHub Desktop.
Run a set of tasks and wait for the first (in run order) that succeed
This file contains 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.Text; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace ConsoleApplication1 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
new Runner().Run(); | |
Console.ReadLine(); | |
} | |
} | |
public class Runner | |
{ | |
private IList<ICalculator> _calculators; | |
private List<KeyValuePair<int, Task<int>>> _calculatorDictionary; | |
private int[] _calculatorResult; | |
private int _lastIndex = -1; | |
private int _finalResult; | |
public Runner() | |
{ | |
_calculators = new List<ICalculator>{ | |
new CalculatorErr(), | |
new GenericCalculator(1, 5000), | |
new GenericCalculator(2, 2000), | |
new GenericCalculator(3, 500), | |
new GenericCalculator(4, 500), | |
new GenericCalculator(5, 500), | |
new GenericCalculator(6, 500), | |
}; | |
} | |
public void Run() | |
{ | |
_calculatorDictionary = new List<KeyValuePair<int, Task<int>>>(); | |
_calculatorResult = Enumerable.Repeat(0, _calculators.Count).ToArray(); ; | |
_calculators.EachWithIndex((c, i) => | |
{ | |
Task<int> t = c.Calculate(i); | |
t.ContinueWith(tt => callback(tt)); | |
_calculatorDictionary.Add(new KeyValuePair<int, Task<int>>(t.GetHashCode(), t)); | |
}); | |
} | |
private void callback(Task<int> task) | |
{ | |
int index = _calculatorDictionary.FindIndex(t => t.Key == task.GetHashCode()); | |
if (!task.IsFaulted) | |
{ | |
_calculatorResult[index] = task.Result; | |
} | |
else | |
{ | |
_calculatorResult[index] = -1; | |
} | |
Console.WriteLine("Callback " + index + " isFaulted: " + task.IsFaulted + " Results: " + ToString(_calculatorResult)); | |
bool allFaulted = true; | |
for (int i = index-1; i >= 0; i--) | |
{ | |
allFaulted &= (_calculatorResult[i] == -1); | |
} | |
if (allFaulted && !task.IsFaulted) | |
{ | |
_finalResult = task.Result; | |
Console.WriteLine("Final result (1): " + _finalResult); | |
} | |
if (allFaulted && task.IsFaulted) | |
{ | |
_finalResult = _calculatorResult.FirstOrDefault(t => t != -1 && t != 0); | |
if (_finalResult != 0) | |
{ | |
Console.WriteLine("Final result (2): " + _finalResult); | |
} | |
} | |
} | |
private string ToString(int[] _calculatorResult) | |
{ | |
string result = "["; | |
_calculatorResult.Each(i => | |
{ | |
result += (i + ", "); | |
}); | |
result = result.Remove(result.Length - 1) + "]"; | |
return result; | |
} | |
} | |
public static class Extensions | |
{ | |
public static void Each<T>(this IEnumerable<T> items, Action<T> action) | |
{ | |
foreach (T item in items) | |
{ | |
action(item); | |
} | |
} | |
public static void EachWithIndex<T>(this IEnumerable<T> items, Action<T, int> action) | |
{ | |
int index = 0; | |
foreach (T item in items) | |
{ | |
action(item, index); | |
index++; | |
} | |
} | |
} | |
public interface ICalculator | |
{ | |
Task<int> Calculate(int x); | |
} | |
public class GenericCalculator : ICalculator | |
{ | |
private int _wait; | |
private int _result; | |
public GenericCalculator(int result, int wait) | |
{ | |
_wait = wait; | |
_result = result; | |
} | |
public Task<int> Calculate(int x) | |
{ | |
return Task.Run(() => | |
{ | |
System.Threading.Thread.Sleep(_wait); | |
return _result; | |
}); | |
} | |
} | |
public class CalculatorErr : ICalculator | |
{ | |
public Task<int> Calculate(int x) | |
{ | |
return Task.Run(() => | |
{ | |
System.Threading.Thread.Sleep(500); | |
throw new Exception(); | |
return 3; | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment