У меня есть несколько стохастических функций, которые возвращают Maybe<T>
.Когда он дает полезный результат, Maybe содержит результат.
Maybe<T>
реализован так:
public readonly struct Maybe<T> {
public readonly bool ContainsValue;
public readonly T Value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Maybe(bool containsValue, T value) {
ContainsValue = containsValue;
Value = value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Maybe<T> Just(T value) {
return new Maybe<T>(
containsValue: true,
value: value);
}
public static Maybe<T> Empty { get; } = new Maybe<T>(
containsValue: false,
value: default
);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Maybe<T>(T value) => Maybe.Just(value);
}
Я бы хотел создать N задач для запуска FuncThatMayFail()
,с N = Environment.ProcessorCount
.Когда первая задача / поток действительно получает полезный результат, он останавливается и сообщает другим задачам / потокам также остановиться.
Мой текущий подход таков:
public static Maybe<T> RunParallel<T>(int maximumRetries, Func<Maybe<T>> func) {
if (maximumRetries < 0)
throw new ArgumentOutOfRangeException(nameof(maximumRetries) + " must be >= 0");
if (func == null)
throw new ArgumentNullException(nameof(func));
var retries = 0;
var tasks = new Task<Maybe<T>>[Environment.ProcessorCount];
var finished = 0;
for (int i = 0; i < tasks.Length; i++) {
tasks[i] = Task.Run(() => {
while (true) {
if (retries >= maximumRetries || finished > 0)
return Maybe<T>.Empty;
var attempt = func();
if (attempt.ContainsValue) {
Interlocked.Increment(ref finished);
return attempt;
} else {
Interlocked.Increment(ref retries);
}
}
});
}
Task.WaitAny(tasks);
for (int i = 0; i < tasks.Length; i++) {
var t = tasks[i];
if (t.IsCompletedSuccessfully && t.Result.ContainsValue)
return t.Result;
}
return Maybe<T>.Empty;
}
Я разместил это наCodereview просил предложения по улучшению и не получил ни одного.Я чувствую, что этот код некрасив и что, вероятно, есть лучший способ сделать это.Есть ли более элегантный (без использования внешних библиотек) для этого?Я использую C # 7.2 для .Net Core 2.2