ContinueWith Method - Как это точно понять? - PullRequest
0 голосов
/ 30 января 2020

Итак, у меня есть, например, этот код здесь:

initialTask.ContinueWith((argument) => { ... });

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

Является ли этот «аргумент» старой задачей или это совершенно новый экземпляр?

Например, когда я хочу обработать отмену первой задачи во второй задаче, должен ли я вызвать:

initialTask.IsCanceled

или

аргумент. IsCanceled

* * 1016

Ответы [ 2 ]

1 голос
/ 30 января 2020

argument - это старая задача. Это предоставляется в качестве аргумента для удобства и эффективности. Без этого лямбда будет вынуждена закрывать переменную initialTask во внешней области видимости, а у замыканий будет служебная память .

1 голос
/ 30 января 2020

Является ли этот «аргумент» старой задачей или это совершенно новый экземпляр?

Да, это ссылка на тот же параметр экземпляра задачи, переданный в качестве параметра в .ContinueWith (т. е. «Старый») - вы можете проверить это следующим образом:

var initialTask = Task.Delay(1000);
initialTask.ContinueWith(t2 => {Debug.Assert(t2 == initialTask);}).Wait();

Причина, по которой передается экземпляр задачи, заключается в том, чтобы предоставить вам доступ к завершенному состоянию и выводу задачи. Но, прежде чем получить доступ к результату t2, вам необходимо выяснить, генерирует ли он исключение (t2.IsFaulted), отменено (t2.IsCanceled) и c, что очень быстро становится беспорядочным.

Вместо этого, теперь, когда C# поддерживает синтаксис async / await, вы должны найти код более простым для чтения и более легким для обработки исключений и т. Д. c, если переписать свой код следующим образом:

async Task MyMethod()
{
   try
   {
      var initialResult = await SomeInitialTask();
      var secondResult = await SecondTask(initialResult); // instead of .ContinueWith and accessing t2.Result
      ... etc.
   }
   catch (Exception ex)
   {
      // Much easier than checking .IsFaulted on each nested task
   }
}  
...