Как разместить параллельно несколько версий рабочего процесса
WorkflowIdentity
предоставляет разработчикам приложений рабочих процессов способ связать имя и версию с определением рабочего процесса, а также связать эти сведения с сохраненным экземпляром рабочего процесса. Эти идентификационные данные могут быть использованы разработчиками приложений рабочего процесса для поддержки таких сценариев, как параллельное выполнение нескольких версий определения рабочего процесса, и являются ключевым элементом для других функциональных возможностей, таких как динамическое обновление. Этот шаг в учебнике показывает, как использовать WorkflowIdentity
для размещения нескольких версий рабочих процессов одновременно.
В этом разделе
На этом этапе учебника действия WriteLine
в рабочем процессе изменены для предоставления дополнительных сведений и добавлено новое действие WriteLine
. Копия исходной сборки рабочего процесса сохранена, а ведущее приложение обновлено для возможности одновременного выполнения исходных и обновленных рабочих процессов.
Примечание.
Перед выполнением действий, описанных в этом разделе, выполните приложение, запустите несколько рабочих процессов каждого типа и укажите одно или два предположения для каждого из них. Эти сохраненные рабочие процессы используются на этом шаге и следующем шаге: обновление определения выполняющегося экземпляра рабочего процесса.
Создание копии проекта NumberGuessWorkflowActivities
Откройте решение WF45GettingStartedTutorial в Visual Studio 2012, если оно не открыто.
Чтобы построить решение, нажмите CTRL+SHIFT+B.
Закройте решение WF45GettingStartedTutorial.
Откройте проводник Windows и перейдите в папку, где находятся файл решения и папки проекта.
Создайте папку с именем PreviousVersions в той же папке, что и NumberGuessWorkflowHost и NumberGuessWorkflowActivities. Эта папка служит для хранения сборок, содержащих различные версии рабочих процессов, которые используются на последующих шагах учебника.
Перейдите в папку NumberGuessWorkflowActivities\bin\debug (или bin\release в зависимости от параметров проекта). Скопируйте NumberGuessWorkflowActivities.dll и вставьте его в папку PreviousVersions .
Переименуйте NumberGuessWorkflowActivities.dll в папке PreviousVersions в NumberGuessWorkflowActivities_v1.dll.
Примечание.
Шаги в этом разделе демонстрируют один способ управления сборками, которые используются для хранения нескольких версий рабочих процессов. Также можно использовать другие методы, такие как строгое наименование сборок и их регистрация в глобальном кэше сборок (GAC).
Создайте новую папку с именем NumberGuessWorkflowActivities_du в той же папке, что и NumberGuessWorkflowActivities, а также только что добавленную папку PreviousVersions, а также скопируйте все файлы и вложенные папки из папки NumberGuessWorkflowActivities в новую папку NumberGuessWorkflowActivities_du. Эта резервная копия проекта для начальной версии действий используется в разделе "Практическое руководство. Обновление определения выполняющегося экземпляра рабочего процесса".
Повторно откройте решение WF45GettingStartedTutorial в Visual Studio 2012.
Обновление рабочих процессов
В этом разделе обновлены определения рабочего процесса. Обновлены два действия WriteLine
, которые получают отзывы на пробное значение пользователя, и добавлено новое действие WriteLine
, которое предоставляет дополнительные сведения об игре, как только будет угадано число.
Обновление рабочего процесса StateMachine
В Обозреватель решений в проекте NumberGuessWorkflowActivities дважды щелкните StateMachineNumberGuesSWorkflow.xaml.
Дважды щелкните неправильный переход на компьютере состояния.
Обновите
Text
крайнего левогоWriteLine
в действииIf
.Guess & " is too low."
Guess + " is too low."
Обновите
Text
крайнего правогоWriteLine
в действииIf
.Guess & " is too high."
Guess + " is too high."
Вернитесь к общему представлению компьютера состояния в конструкторе рабочих процессов, щелкнув StateMachine в области навигации в верхней части конструктора рабочих процессов.
Дважды щелкните переход "Угадывание правильно" на компьютере состояния.
Перетащите действие WriteLine из раздела "Примитивы" панели элементов и удалите его в действие drop Action здесь метка перехода.
В поле свойств
Text
введите следующее выражение.Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
Обновление рабочего процесса блок-схемы
В Обозреватель решений в проекте NumberGuessWorkflowActivities дважды щелкните FlowchartNumberGuessWorkflow.xaml.
Обновите
Text
крайнего левого действияWriteLine
.Guess & " is too low."
Guess + " is too low."
Обновите
Text
крайнего правого действияWriteLine
.Guess & " is too high."
Guess + " is too high."
Перетащите действие WriteLine из раздела "Примитивы" панели элементов и удалите его в точку
True
падения действия самого верхнегоFlowDecision
уровня. ДействиеWriteLine
добавляется к блок-схеме и связывается с действиемTrue
FlowDecision
.В поле свойств
Text
введите следующее выражение.Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
Обновление последовательного рабочего процесса
В Обозреватель решений в проекте NumberGuessWorkflowActivities дважды щелкните sequentialNumberGuessWorkflow.xaml.
Обновите
Text
крайнего левогоWriteLine
в действииIf
.Guess & " is too low."
Guess + " is too low."
Обновите
Text
крайнего правого действияWriteLine
в действииIf
.Guess & " is too high."
Guess + " is too high."
Перетащите действие WriteLine из раздела "Примитивы" панели элементов и удалите его после действия DoTime, чтобы строка записи была окончательной в корневом
Sequence
действии.В поле свойств
Text
введите следующее выражение.Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
Обновление WorkflowVersionMap для включения предыдущих версий рабочих процессов
Дважды щелкните WorkflowVersionMap.cs (или WorkflowVersionMap.vb) в проекте NumberGuessWorkflowHost , чтобы открыть его.
Добавьте следующие инструкции
using
(илиImports
) в начало файла с другими инструкциямиusing
(илиImports
).Imports System.Reflection Imports System.IO
using System.Reflection; using System.IO;
Добавьте три новых идентификатора рабочих процессов непосредственно под тремя существующими объявлениями идентификаторов рабочих процессов. Эти новые идентификаторы рабочих процессов
v1
будут использоваться для получения правильных определений рабочих процессов перед выполнением обновлений.'Current version identities. Public StateMachineNumberGuessIdentity As WorkflowIdentity Public FlowchartNumberGuessIdentity As WorkflowIdentity Public SequentialNumberGuessIdentity As WorkflowIdentity 'v1 Identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 As WorkflowIdentity
// Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentity; static public WorkflowIdentity FlowchartNumberGuessIdentity; static public WorkflowIdentity SequentialNumberGuessIdentity; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1;
В конструкторе
WorkflowVersionMap
обновите свойствоVersion
трех текущих идентификаторов рабочих процессов до2.0.0.0
.'Add the current workflow version identities. StateMachineNumberGuessIdentity = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } FlowchartNumberGuessIdentity = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } SequentialNumberGuessIdentity = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } map.Add(StateMachineNumberGuessIdentity, New StateMachineNumberGuessWorkflow()) map.Add(FlowchartNumberGuessIdentity, New FlowchartNumberGuessWorkflow()) map.Add(SequentialNumberGuessIdentity, New SequentialNumberGuessWorkflow())
// Add the current workflow version identities. StateMachineNumberGuessIdentity = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; FlowchartNumberGuessIdentity = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; SequentialNumberGuessIdentity = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow()); map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow()); map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow());
Код, который добавляет текущие версии рабочих процессов в словарь, использует текущие версии, которые указаны в проекте, чтобы код, который инициализирует определения рабочего процесса, не нужно было обновлять.
Добавьте следующий код в конструктор сразу после кода, добавляющего текущие версии в словарь.
'Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } FlowchartNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } SequentialNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) }
// Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; FlowchartNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; SequentialNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) };
Эти удостоверения рабочих процессов связаны с первоначальными версиями соответствующих определений рабочих процессов.
Затем загрузите сборку, которая содержит первоначальную версию определений рабочих процессов, создайте соответствующие определения рабочих процессов и добавьте их в словарь.
'Add the previous version workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v1 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v1AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll" v1AssemblyPath = Path.GetFullPath(v1AssemblyPath) Dim v1Assembly As Assembly = Assembly.LoadFile(v1AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow"))
// Add the previous version workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v1 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v1AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll"; v1AssemblyPath = Path.GetFullPath(v1AssemblyPath); Assembly v1Assembly = Assembly.LoadFile(v1AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity);
Ниже приведен полный список для обновленного класса
WorkflowVersionMap
.Public Module WorkflowVersionMap Dim map As Dictionary(Of WorkflowIdentity, Activity) 'Current version identities. Public StateMachineNumberGuessIdentity As WorkflowIdentity Public FlowchartNumberGuessIdentity As WorkflowIdentity Public SequentialNumberGuessIdentity As WorkflowIdentity 'v1 Identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 As WorkflowIdentity Sub New() map = New Dictionary(Of WorkflowIdentity, Activity) 'Add the current workflow version identities. StateMachineNumberGuessIdentity = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } FlowchartNumberGuessIdentity = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } SequentialNumberGuessIdentity = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } map.Add(StateMachineNumberGuessIdentity, New StateMachineNumberGuessWorkflow()) map.Add(FlowchartNumberGuessIdentity, New FlowchartNumberGuessWorkflow()) map.Add(SequentialNumberGuessIdentity, New SequentialNumberGuessWorkflow()) 'Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } FlowchartNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } SequentialNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } 'Add the previous version workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v1 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v1AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll" v1AssemblyPath = Path.GetFullPath(v1AssemblyPath) Dim v1Assembly As Assembly = Assembly.LoadFile(v1AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow")) End Sub Public Function GetWorkflowDefinition(identity As WorkflowIdentity) As Activity Return map(identity) End Function Public Function GetIdentityDescription(identity As WorkflowIdentity) As String Return identity.ToString() End Function End Module
public static class WorkflowVersionMap { static Dictionary<WorkflowIdentity, Activity> map; // Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentity; static public WorkflowIdentity FlowchartNumberGuessIdentity; static public WorkflowIdentity SequentialNumberGuessIdentity; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1; static WorkflowVersionMap() { map = new Dictionary<WorkflowIdentity, Activity>(); // Add the current workflow version identities. StateMachineNumberGuessIdentity = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; FlowchartNumberGuessIdentity = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; SequentialNumberGuessIdentity = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow()); map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow()); map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow()); // Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; FlowchartNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; SequentialNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; // Add the previous version workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v1 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v1AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll"; v1AssemblyPath = Path.GetFullPath(v1AssemblyPath); Assembly v1Assembly = Assembly.LoadFile(v1AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity); } public static Activity GetWorkflowDefinition(WorkflowIdentity identity) { return map[identity]; } public static string GetIdentityDescription(WorkflowIdentity identity) { return identity.ToString(); } }
Построение и запуск приложения
Нажмите сочетание клавиш CTRL+SHIFT+B, чтобы построить приложение, а затем сочетание клавиш CTRL+F5 для его запуска.
Запустите новый рабочий процесс, нажав кнопку "Создать игру". Версия рабочего процесса отображается под окном состояния и отображает обновленную версию из связанного
WorkflowIdentity
. ЗапишитеInstanceId
, чтобы просмотреть файл отслеживания для рабочего процесса после его завершения, а затем вводите предположения, пока игра не завершится. Обратите внимание на то, что догадка пользователя отображается в окне состояния в зависимости от обновлений действийWriteLine
.Please enter a number between 1 and 10 5 is too high. Please enter a number between 1 and 10 3 is too high. Please enter a number between 1 and 10 1 is too low. Please enter a number between 1 and 10 Congratulations, you guessed the number in 4 turns.
Примечание.
Отображается обновленный текст из действий
WriteLine
, но выходные данные последнего действияWriteLine
, которое было добавлено в этом разделе, отсутствуют. Это происходит потому, что окно состояния обновляется обработчикомPersistableIdle
. Поскольку рабочий процесс завершается, а не переходит в состояние бездействия после окончательного действия, обработчикPersistableIdle
не вызывается. Однако похожее сообщение отображается обработчикомCompleted
в окне состояния. Если необходимо, код можно добавить в обработчикCompleted
, чтобы извлечь текст изStringWriter
и показать его в окне состояния.Откройте Windows Обозреватель и перейдите в папку NumberGuessWorkflowHost\bin\debug (или bin\release в зависимости от параметров проекта) и откройте файл отслеживания с помощью Блокнот, соответствующего завершенным рабочим процессам. Если вы не заметите
InstanceId
, можно определить правильный файл отслеживания с помощью сведений об изменении даты в Windows Обозреватель.Please enter a number between 1 and 10 5 is too high. Please enter a number between 1 and 10 3 is too high. Please enter a number between 1 and 10 1 is too low. Please enter a number between 1 and 10 2 is correct. You guessed it in 4 turns.
Обновленные выходные данные
WriteLine
содержатся в файле отслеживания, в том числе выходные данные трассировки действияWriteLine
, добавленного в этом разделе.Перейдите к приложению отгадывания чисел и выберите один из рабочих процессов, который был запущен до выполнения обновлений. Вы можете указать версию выбранного в данный момент рабочего процесса, посмотрев сведения о версии, отображаемые под окном состояния. Введите несколько предположений и обратите внимание на то, что некоторые обновления состояния соответствуют выходным данным действия
WriteLine
из предыдущей версии, но не включают предположение пользователя. Это происходит потому, что такие рабочие процессы используют предыдущее определение рабочего процесса, в котором не выполнены обновленияWriteLine
.На следующем шаге: обновление определения выполняющегося экземпляра рабочего процесса обновляется,
v1
чтобы они содержали новые функциональные возможности в качествеv2
экземпляров.