Множественная параллельная задача. Продолжение с порядком выполнения
Вопрос
Это, наверное, что-то простое, что я пропустил.
Скажем, я делаю (в Loveley VB):
Dim t1 As New Task(Sub() Debug.WriteLine("t1"))
Dim t2 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t2"))
Dim t3 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t3"))
t1.Start()
Обратите внимание: t1.ContinueWith используется дважды. Каков предпочтительный порядок выполнения этих задач? Для меня это случайное или неправильное.
Почему?
Причина, по которой я хочу это сделать...
- Создать задачу захвата и возврата данных
- После выполнения задачи, которая "сортирует" пользовательский интерфейс на
TaskScheduler.FromCurrentSynchronizationContext()
(поток пользовательского интерфейса)
- Следуйте первоначальной задаче захвата данных, преобразуя данные в длинный отчет (требуется возраст)
- Вернитесь в поток пользовательского интерфейса, присвойте этому отчету элементу управления предварительным просмотром
- Очистка (избавиться от моей анимации прогресса и т.д.)
Это усложняется тем фактом, что шаг 4 является необязательным.
Посреди всего этого мои задачи гибки назад, чтобы установить свойства элемента, чтобы пользовательский интерфейс и задачи могли играть хорошо. Возможно, я должен полностью удалить результат задачи и просто придерживаться Synclocking моих переменных-членов. Все они назначаются только один раз после.
Спасибо, Том
Ответы
Ответ 1
Задачи выполняются в порядке LIFO для лучшей локальности памяти. Это может быть изменено, конечно, если вы используете планировщик differnt или если MS решит "исправить" оригинал. Я не думаю, что вы должны полагаться на это поведение. Вместо этого вы можете распаковать свою задачу, чтобы продолжить работу над предыдущей задачей, когда она завершилась. В противном случае вы ждете не того. Более подробную информацию можно найти здесь: http://msdn.microsoft.com/en-us/library/ee795275.aspx
Ответ 2
Если вы хотите обеспечить соблюдение порядка между t2 и t3, почему бы вам просто не изменить, так что t3 продолжается от t2 вместо t1?
Dim t1 As New Task(Sub() Debug.WriteLine("t1"))
Dim t2 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t2"))
Dim t3 As Task = t2.ContinueWith(Sub() Debug.WriteLine("t3"))
t1.Start()
Если t2 и t3 были длинными, они будут выполняться параллельно, как вы это делали.
Нет необходимости создавать настраиваемый планировщик задач, чтобы изменить это поведение.
Ответ 3
Основываясь на вашем комментарии к ответу Яна Мерсера, я бы предложил что-то вроде
Task t1 = new Task((_)=>Console.WriteLine("t1"));
Task tn = secondTaskCondition ? t1.ContinueWith((_)=>Console.WriteLine("t2")) : t1;
Task t3 = tn.ContinueWith((_)=>Console.WriteLine("t3"));
t1.Start();
Это дает вам детерминированное выполнение и по-прежнему позволяет вам компоновать рабочий процесс с помощью дополнительных модулей.