2

Я читаю книгу под названием Pro .NET 4 Parallel Programming in C# от Адама Фримана. В главе 2 на стр. 13 он говорит об использовании Task<int>, чтобы вернуть результат, используя task1.Result, чтобы дождаться его завершения. Я не понимаю, почему task2 должен дождаться task1. Они находятся на разных потоках.C# .net 4 параллельное программирование

Это то, что, как показано ниже:

Task<int> task1 = new Task<int>(() => { ... ; return sum }); 
task1.Start(); 
Console.WriteLine("Result 1: {0}", task1.Result); 

Task<int> task2 = new Task<int>(() => { ... ; return sum }); 
task2.Start(); 
Console.WriteLine("Result 2: {0}", task2.Result); 

Если я перееду в следующую строку в нижней части, что кажется, как task1 все еще выполняет первый, независимо от того, сколько раз я пытался.

Console.WriteLine("Result 1: {0}", task1.Result); 

Почему это происходит?

ответ

0

Задача, которая на самом деле заканчивается первой - то есть, сначала обращается к ее заявлению о возврате - это, формально, непредсказуемо. Они могут закончить свою работу, прежде чем принять их результаты.

Если работа, выполняемая вашими образцовыми задачами, не очень велика, это означает, что задача1 будет завершена первой, даже если вы не принимаете ее результат (или в Java threading lingo, join it) в первую очередь. Это потому, что вы начали сначала.

Предположительно, вы как-то знаете, что задача1 закончена первой. Есть ли Console.WriteLine в коде для ваших задач? Если это так, имейте в виду, что подсистема Console выполняет сериализацию операций, поэтому первая из ваших задач, которую она будет использовать, сделает это полностью до того, как начнется вторая. Подумайте об этом так: ваши две задачи бегут на консоль, и победитель получает все.

Задача 1 имеет несправедливое преимущество в этой гонке, потому что она выключена и работает до того, как ваша основная нить даже начнет строить task2 с вашей второй new.

+0

Спасибо за ваш ответ – Fei

3

Task.Result блокировки до завершения Task.

Для этого необходимо вернуть результат!

Итак, в вашем первом примере task2 даже не начался, пока task1 не был завершен.

Если вы перемещаете task1.Result в нижнюю часть, то неопределенная задача завершается первой, но ваши операторы Console.WriteLine будут выполняться в последовательном порядке.

+0

Николас, спасибо, что ответили. Я могу понять задачу. Результат будет ждать завершения задачи.Если task1 уже запущен, я не могу запустить другую задачу (поток) для выполнения? Ниже приведен еще один пример: foreach (строка msg в сообщениях) {Task tsk = new Task (obj => printMsg (obj), msg); tsk.Start();}. Эти задачи внутри цикла foreach выполняются параллельно. – Fei

0

Попробуйте использовать метод task.Wait().

 Task<int> task1 = new Task<int>(() => { int sum = 0; return sum; }); 
     task1.Start(); 
     task1.Wait(); 
     Console.WriteLine("Result 1: {0}", task1.Result); 

     Task<int> task2 = new Task<int>(() => { int sum = Enumerable.Range(1, 10).Sum(); return sum; }); 
     task2.Start(); 
     task1.Wait(); 
     Console.WriteLine("Result 2: {0}", task2.Result); 
+0

Он должен дать тот же результат, но его гораздо легче читать, так как вы явно «ждите». – Bengie

+0

Спасибо за ваш ответ. – Fei

0

"Console.WriteLine (" Результат 1: {0} ", task1.Result);" не может работать до тех пор, пока задача 1 не завершится, поэтому она ждет/блокирует.

Хотя задачи выполняются независимо друг от друга, вызывающий поток вызывает console.writeline в последовательном порядке. Результаты этих двух задач вынуждены быть в порядке.

0

Task task1 = new Task(() => { ... ; return sum });
task1.Start();
Task task2 = new Task(() => { ... ; return sum });
task2.Start();
task1.Wait()
Console.WriteLine("Result 1: {0}", task1.Result);
task2.Wait()
Console.WriteLine("Result 2: {0}", task2.Result);

Попробуйте это. Здесь вам нужно запустить обе задачу перед вызовом console.writeline.

Смежные вопросы