Я использую Windows WF прямо сейчас для простого способа определения состояния машин. На самом деле, я даже не использую конечный автомат, я использую последовательный рабочий процесс. Со временем я откажусь от WF в пользу чего-то другого, но так как у меня уже есть работающий код, мне нужно, чтобы работали методы Abort, Suspend и Resume.
Мое приложение порождает поток, который затем порождает другой поток, которому принадлежит WorkflowInstance. В моем графическом интерфейсе есть кнопки «Прервать», «Пауза» и «Возобновить», которые в конечном итоге вызывают методы «Прервать», «Приостановить» и «Возобновить» в WorkflowInstance соответственно.
Проблема в том, что когда я делаю это, я получаю очень большой и страшный MessageBox, который говорит:
В среде размещения рабочего процесса нет службы персистентности, как требуется для операции с экземпляром рабочего процесса
вместе с хорошей трассировкой стека и все. Теперь я посмотрел эти методы в Pro WF Брюса Буковича , и один из его примеров называет эти методы, и нигде не упоминалось о «службе персистентности». Однако его примеры вызовов были в рамках WorkflowRuntime, то есть он вызывает их так:
using(WorkflowRuntimeManager manager = new WorkflowRuntimeManager(new WorkflowRuntime("WorkflowRuntime")))
{
manager.WorkflowRuntime.StartRuntime();
WorkflowInstanceWrapper instance = manager.StartWorkflow(typeof(SharedWorkflows.Workflow1), null);
instance.Suspend("Manually suspended");
instance.Resume();
waitHandle.WaitOne();
}
В своем приложении я реализовал WorkflowRuntime как одиночный, потому что обнаружил, что при создании WorkflowRuntime, как этот, произошла огромная утечка памяти. Итак, мой код выглядит так:
WorkflowInstance instance = WorkflowRuntimeSingleton.Instance.workflow_runtime.CreateWorkflow(typeof(SharedWorkflows.Workflow1), null);
instance.Start();
instance.Suspend("Manually suspended");
instance.Resume();
waitHandle.WaitOne();
Теперь, если я вызову Suspend и Resume, как показано выше, все работает нормально. Но если я выполняю вызов через мой графический интерфейс, он жалуется на постоянную службу.
Учитывая эту информацию и то, что я не хочу создавать базу данных только для того, чтобы получить эти три функции, я хотел бы знать, что мне нужно сделать, чтобы эта работа работала. На данный момент я предпочитаю, что WF не нравится, когда его контролируют из отдельного потока. Если это так, есть ли хороший способ сделать так, чтобы вызов выглядел так, как будто он был сделан из того же потока?
Вот несколько возможных решений, которые я придумала, но я уверен, что у кого-то здесь есть более изящный и элегантный способ сделать это.
- WF-запросы на прерывание / паузу / возобновление через интерфейс с графическим интерфейсом (кажется, очень неубедительным)
- Замените WaitOne () на WaitAny (), и вызовите графический интерфейс объекта, которому принадлежит рабочий процесс, установите AutoResetEvent. WaitAny () позволяет продолжить выполнение, а затем мой код может проверить, какую кнопку нажал пользователь. Это нужно будет заключить в цикл, чтобы мы могли снова подождать, пока пользователь не нажмет кнопку «Прервать», или пока WF не будет завершен.
- использовать логический флаг, чтобы в основном делать то, что делает # 2.
- посмотрим, знает ли кто-нибудь на SO, как волшебным образом сделать вызов в правом потоке:)
Любое понимание или мнения будут очень признательны!