Некоторое время я пытался получить то, что, как мне казалось, было бы просто работать с .NET 4.5.
Я хочу запустить две длительные задачи одновременно и собрать
результаты лучшим способом C # 4.5 (RTM)
Следующее работает, но мне это не нравится, потому что:
- Я хочу
Sleep
быть асинхронным методом, чтобыawait
другие методы - Это выглядит неуклюже с
Task.Run()
- Я не думаю, что здесь вообще используются какие-либо новые языковые функции!
Рабочий код:
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Task.Run(() => Sleep(5000));
var task2 = Task.Run(() => Sleep(3000));
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}
private static int Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
Console.WriteLine("Sleeping for " + ms + " FINISHED");
return ms;
}
Нерабочий код:
Обновление: это действительно работает, и это правильный способ сделать это, единственная проблема - это Thread.Sleep
Этот код не работает, потому что вызов Sleep(5000)
немедленно запускает задачу, поэтому Sleep(1000)
не запускается, пока она не будет завершена. Это верно , даже если Sleep
это async
и я не использую await
или позвонив по телефону .Result
слишком рано.
Я подумал, может быть, есть способ отключить запуск Task<T>
, вызвав async
метод, чтобы я мог затем вызватьStart()
две задачи, но я не могу понять, как получить Task<T>
от вызова асинхронного метода.
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Sleep(5000); // blocks
var task2 = Sleep(1000);
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for " + totalSlept + " ms");
}
private static async Task<int> Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
return ms;
}
источник
task1.Result
not at,var task1 = Sleep(5000)
потому что ваш метод Sleep без ключевого слова await является синхронным.Ответы:
Для асинхронного программирования следует использовать Task.Delay вместо Sleep, а затем использовать Task.WhenAll для объединения результатов задачи. Задачи будут выполняться параллельно.
источник
источник
Go
является синхронным, но хочет выполнить две независимые задачи асинхронно (т.е. ни одна из них не должна завершаться раньше другой, но обе должны завершиться до продолжения выполнения), тогдаTask.WaitAll
было бы лучше, и вы не должны Ключевое слово await не требуется, поэтому не нужно, чтобы вызывающийGo
метод был сам по себе асинхронным. Ни один из подходов не лучше, это просто вопрос вашей цели.async void LongTask1() {...}
Метод Void: не имеет свойства Task.Result. Используйте задачу без Т в таком случае:async Task LongTask1()
.Task<TResult> t1 = LongTask1();
и теперь получаюt1.Result
.<TResult>
- это возвращаемый тип вашего результата.return <TResult>
Чтобы это работало, вам понадобится метод.t1
иt2
переменных, вы можете использоватьnew Task(...)
. Например:int int1 = 0; await Task.WhenAll(new Task(async () => { int1 = await LongTask1(); }));
. Уловка этого подхода заключается в том, что компилятор не распознает, что переменная была назначена, и будет рассматривать ее как неназначенную, если вы не укажете ей начальное значение.Пока ваш
Sleep
метод асинхронный,Thread.Sleep
это не так. Вся идея async заключается в повторном использовании одного потока, а не в запуске нескольких потоков. Поскольку вы заблокировали использование синхронного вызова Thread.Sleep, это не сработает.Я предполагаю, что
Thread.Sleep
это упрощение того, что вы действительно хотите делать. Можно ли закодировать вашу фактическую реализацию как асинхронные методы?Если вам действительно нужно запустить несколько синхронных вызовов блокировки, поищите в другом месте, я думаю!
источник
var x = y()
а неvar x=await y()
илиy().wait()
еще подождите, и если async не справится с этим сам по себе, что мне делать? ОБРАТИТЕ ВНИМАНИЕ, что y украшен async, и я ожидаю, что он будет делать все в пределах, когда все, а не прямо там, где он назначен, РЕДАКТИРОВАТЬ: я просто когда моему партнеру сказал, давай попробуемTask.Factory
, и он сказал, что это сработало, когда я выйду сторона этого классаЧтобы ответить на этот вопрос:
вы можете переписать
Sleep
функцию следующим образом:запуск этого кода выведет:
источник
Сейчас выходные !
источник
Эта статья помогла многое объяснить. Это в стиле FAQ.
Async / Await FAQ
Эта часть объясняет, почему
Thread.Sleep
работает в одном и том же исходном потоке, что привело к моей первоначальной путанице.источник