【发布时间】:2019-01-28 12:57:43
【问题描述】:
我想要一个接收Task<bool> 并在 X 任务中运行它的函数。
为此,我编写了以下代码:
public static class RetryComponent
{
public static async Task RunTasks(Func<Task<bool>> action, int tasks, int retries, string method)
{
// Running everything
var tasksPool = Enumerable.Range(0, tasks).Select(i => DoWithRetries(action, retries, method)).ToArray();
await Task.WhenAll(tasksPool);
}
private static async Task<bool> DoWithRetries(Func<Task<bool>> action, int retryCount, string method)
{
while (true)
{
if (retryCount <= 0)
return false;
try
{
bool res = await action();
if (res)
return true;
}
catch (Exception e)
{
// Log it
}
retryCount--;
await Task.Delay(200); // retry in 200
}
}
}
以及如下执行代码:
BlockingCollection<int> ints = new BlockingCollection<int>();
foreach (int i in Enumerable.Range(0, 100000))
{
ints.Add(i);
}
ints.CompleteAdding();
int taskId = 0;
var enumerable = new AsyncEnumerable<int>(async yield =>
{
await RetryComponent.RunTasks(async () =>
{
try
{
int myTaskId = Interlocked.Increment(ref taskId);
// usually there are async/await operations inside the while loop, this is just an example
while (!ints.IsCompleted)
{
int number = ints.Take();
Console.WriteLine($"Task {myTaskId}: {number}");
await yield.ReturnAsync(number);
}
}
catch (InvalidOperationException)
{
return true;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return true;
}, 10, 1, MethodBase.GetCurrentMethod().Name);
});
await enumerable.ForEachAsync(number =>
{
Console.WriteLine(number);
});
AsyncEnumerable 来自System.Collections.Async。
控制台显示任务 10:X(其中 x 是列表中的数字..)。
当我删除 AsyncEnumerable 时,一切都按预期工作(所有任务都在打印并且执行结束)..
出于某种原因,我很长时间都找不到,使用AsyncEnumerable 只会破坏一切(在我的主代码中,我需要它来使用AsyncEnumerable.. 可扩展性的东西..)这意味着代码永远不会停止,只有最后一个任务 (10) 正在打印。当我添加更多日志时,我发现任务 1-9 永远不会完成。
所以只是为了澄清问题,我想让多个任务执行异步操作并将结果生成给一个充当管道的 AsyncEnumerable 对象。 (这就是想法..)
【问题讨论】:
-
它是如何毁掉一切的?
-
因为当它不在 AsyncEnumerable 中时,事情会按预期工作并且所有任务都在打印(而不仅仅是任务 10。)另外,这个任务不会结束,因为任务 1-9 永远不会完成,原因是我不知道
-
所以使用
AsyncEnumerable,它只打印Task 10: {number}?请记住,在表述问题时,只有您了解其背后的背景,最好描述问题和预期/预期的解决方案以帮助我们理解。 -
我想我现在说得更清楚了。
标签: c# multithreading async-await