Как мне преобразовать это в асинхронную задачу?
Учитывая следующий код ...
static void DoSomething(int id) {
Thread.Sleep(50);
Console.WriteLine(@"DidSomething({0})", id);
}
Я знаю, что могу преобразовать это в асинхронную задачу следующим образом ...
static async Task DoSomethingAsync(int id) {
await Task.Delay(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
}
И так, если я буду звонить несколько раз (Task.WhenAll), все будет быстрее и эффективнее, чем, возможно, использование Parallel.Foreach или даже вызов из цикла.
Но на минуту давайте представим, что Task.Delay () не существует, и мне действительно нужно использовать Thread.Sleep (); Я знаю, что на самом деле это не так, но это концептуальный код, и когда задержка / спящий режим обычно является операцией ввода-вывода, когда нет опции асинхронизации (такой как ранний EF).
Я попробовал следующее ...
static async Task DoSomethingAsync2(int id) {
await Task.Run(() => {
Thread.Sleep(50);
Console.WriteLine(@"DidSomethingAsync({0})", id);
});
}
Но, хотя он работает без ошибок, в соответствии сЛюсьен Висчик на самом деле это плохая практика, так как это просто раскручивание потоков из пула для выполнения каждой задачи (это также медленнее при использовании следующего консольного приложения - если вы переключаетесь между вызовами 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 в асинхронной задаче, как вы делаете это так же эффективно, как исходный код?
Цель для тех из вас, кто заинтересован, состоит в том, чтобы дать мне лучшее понимание того, как создавать мои собственные асинхронные методы, когда я не называю кого-либо еще. Несмотря на множество поисков, это, по-видимому, единственная область, где примеров действительно не хватает - хотя существует множество тысяч примеров вызова асинхронных методов, которые в свою очередь вызывают другие асинхронные методы, я не могу найти ни одного, который преобразует существующий метод void в асинхронную задачу, где нет вызова для другой асинхронной задачи, кроме тех, которые используют метод Task.Run (() => {}).