Task.Delay запускает новую тему?
Следующий код должен (по крайней мере, на мой взгляд) создать 100Tasks
, которые все ждут параллельно (в этом суть параллелизма, верно: D?) и заканчиваются почти одновременно. Я думаю, для каждогоTask.Delay
a Timer
Объект создан внутри.
public static async Task MainAsync() {
var tasks = new List<Task>();
for (var i = 0; i < 100; i++) {
Func<Task> func = async () => {
await Task.Delay(1000);
Console.WriteLine("Instant");
};
tasks.Add(func());
}
await Task.WhenAll(tasks);
}
public static void Main(string[] args) {
MainAsync().Wait();
}
Но! Когда я запускаю это на Mono, я получаю очень странное поведение:
Tasks
не заканчивайте в то же время, есть огромные задержки (вероятно, около 500-600 мс)В консоли моно показано множество созданных тем:Загруженная сборка: /Users/xxxxx/Programming/xxxxx/xxxxxxxxxx/bin/Release/xxxxx.exe
Тема начата: # 2
Тема начата: # 3
Тема начата: # 4
Тема начата: # 5
Тема начата: # 6
Тема начата: # 7
Тема закончена: # 3 <- Очевидно, задержка в 1000 мс закончена?
Тема закончена: # 2 <- Очевидно, задержка в 1000 мс закончена?
Тема начата: # 8
Тема начата: # 9
Тема начата: # 10
Тема начата: # 11
Тема начата: # 12
Тема начата: # 13
... ты понял.
Это на самом деле ошибка? Или я неправильно использую библиотеку?
[РЕДАКТИРОВАТЬ] Я проверил пользовательский метод сна с использованием таймера:
public static async Task MainAsync() {
Console.WriteLine("Started");
var tasks = new List<Task>();
for (var i = 0; i < 100; i++) {
Func<Task> func = async () => {
await SleepFast(1000);
Console.WriteLine("Instant");
};
tasks.Add(func());
}
await Task.WhenAll(tasks);
Console.WriteLine("Ready");
}
public static Task SleepFast(int amount) {
var source = new TaskCompletionSource<object>();
new Timer(state => {
var oldSrc = (TaskCompletionSource<object>)state;
oldSrc.SetResult(null);
}, source, amount, 0);
return source.Task;
}
На этот раз все задачи выполнены мгновенно. Итак, я думаю, что это действительно плохая реализация или ошибка.
[Edit2] Просто к вашему сведению: я проверил оригинальный код (используяTask.Delay
) на .NET теперь используется Windows 8.1, и он работает как ожидалось (1000Tasks
, жду 1 секунду параллельно и заканчиваю).
Таким образом, ответ: Моно вкл. из (некоторых) методов не идеален. В общемTask.Delay
не запускает поток, и даже многие из них не должны создавать несколько потоков.