我创建了对Enumerable的扩展以快速执行动作,因此我列出了该方法,并进行了循环,如果对象在特定时间内执行该方法,我会返回, 现在,我想使输出通用,因为方法输出将有所不同,有关如何处理的任何建议
这个IEnumerable进程,就像负载均衡一样,如果第一个没有响应,第二个应该响应,我想返回输入Action的输出
Plumber Related
此代码的运行方式
public static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> source, Action action, int timeOut)
{
foreach (T element in source)
{
lock (source)
{
// Loop for all connections and get the fastest responsive proxy
foreach (var mxAccessProxy in source)
{
try
{
// check for the health
Task executionTask = Task.Run(action);
if (executionTask.Wait(timeOut))
{
return ;
}
}
catch
{
//ignore
}
}
}
}
}
}
答案 0 :(得分:3)
这将提高性能和代码可读性
不,它绝对不会:)此外,此代码还会带来更多问题,例如冗余锁定或吞咽异常,但实际上并不能并行执行代码。
似乎您想使用某种代理对象来为您的Action
获得最快的通话。您需要异步运行Tasks
,而不是.Wait()
。
类似的事情可能对您有帮助:
public static class TaskExtensions
{
public static TReturn ParallelSelectReturnFastest<TPoolObject, TReturn>(this TPoolObject[] pool,
Func<TPoolObject, CancellationToken, TReturn> func,
int? timeout = null)
{
var ctx = new CancellationTokenSource();
// for every object in pool schedule a task
Task<TReturn>[] tasks = pool
.Select(poolObject =>
{
ctx.Token.ThrowIfCancellationRequested();
return Task.Factory.StartNew(() => func(poolObject, ctx.Token), ctx.Token);
})
.ToArray();
// not sure if Cast is actually needed,
// just to get rid of co-variant array conversion
int firstCompletedIndex = timeout.HasValue
? Task.WaitAny(tasks.Cast<Task>().ToArray(), timeout.Value, ctx.Token)
: Task.WaitAny(tasks.Cast<Task>().ToArray(), ctx.Token);
// we need to cancel token to avoid unnecessary work to be done
ctx.Cancel();
if (firstCompletedIndex == -1) // no objects in pool managed to complete action in time
throw new NotImplementedException(); // custom exception goes here
return tasks[firstCompletedIndex].Result;
}
}
现在,您可以使用此扩展方法在任何对象池上调用特定操作并获取第一个执行结果:
var pool = new[] { 1, 2, 3, 4, 5 };
var result = pool.ParallelSelectReturnFastest((x, token) => {
Thread.Sleep(x * 200);
token.ThrowIfCancellationRequested();
Console.WriteLine("calculate");
return x * x;
}, 100);
Console.WriteLine(result);
它输出:
计算 1
因为第一个任务将在200毫秒内完成工作,将其返回,并且所有其他任务将通过取消令牌被取消。
在您的情况下,它将类似于:
var actionResponse = proxiesList.ParallelSelectReturnFastest((proxy, token) => {
token.ThrowIfCancellationRequested();
return proxy.SomeAction();
});
有些事情要提:
CreateItem
,那么最终可以通过不同的代理创建许多项目Func
将返回任务,并且您需要使用await Task.WhenAny(tasks)
而不是Task.WaitAny()