Учитывая следующий код...
static void DoSomething(int id) {
Thread.Sleep(50);
Console.WriteLine(@"DidSomething({0})", id);
}
Я знаю, что могу преобразовать это в async-задачу следующим образом...
static async Task DoSomethingAsync(int id) {
await Task.Delay(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
}
И если это произойдет, если я звоню несколько раз (Task.WhenAll), все будет быстрее и эффективнее, чем, возможно, использовать Parallel.Foreach или даже вызывать из цикла.
Но на минуту давайте сделаем вид, что Task.Delay() не существует, и мне действительно нужно использовать Thread.Sleep(); Я знаю, что на самом деле это не так, но это код концепции и где Delay/Sleep обычно является операцией ввода-вывода, где нет опции async (например, раннего EF).
Я пробовал следующее...
static async Task DoSomethingAsync2(int id) {
await Task.Run(() => {
Thread.Sleep(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
});
}
Но, хотя он работает без ошибок, согласно Lucien Wischik, это на самом деле плохая практика, поскольку она просто разворачивает потоки из пула для выполнения каждой задачи ( он также работает медленнее, используя следующее консольное приложение - если вы меняете обмен между вызовами DoSomethingAsync и DoSomethingAsync2, вы можете увидеть значительную разницу в времени, которое требуется для завершения)...
static void Main(string[] args) {
MainAsync(args).Wait();
}
static async Task MainAsync(String[] args) {
List<Task> tasks = new List<Task>();
for (int i = 1; i <= 1000; i++)
tasks.Add(DoSomethingAsync2(i)); // Can replace with any version
await Task.WhenAll(tasks);
}
Затем я попробовал следующее...
static async Task DoSomethingAsync3(int id) {
await new Task(() => {
Thread.Sleep(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
});
}
Пересажая это вместо оригинального DoSomethingAsync, тест никогда не завершается, и на экране ничего не отображается!
Я также пробовал несколько других вариантов, которые либо не компилируются, либо не заполняются!
Итак, учитывая ограничение, которое вы не можете назвать любыми существующими асинхронными методами и должно выполнить как Thread.Sleep, так и Console.WriteLine в асинхронной задаче, как вы это сделаете так же эффективно, как и исходный код
Цель для тех из вас, кто интересуется, - дать мне лучшее представление о том, как создавать свои собственные методы асинхронного программирования, где я не звоню никому. Несмотря на многие поисковые запросы, это, по-видимому, та область, где примеров действительно не хватает - в то время как существует много тысяч примеров вызова методов async, которые вызывают другие методы async, в свою очередь, я не могу найти какие-либо преобразования существующего метода void в async-задачу, нет вызова другой асинхронной задачи, отличной от тех, которые используют метод Task.Run(() = > {}).