Вызвать рабочий процесс WF из службы WCF - PullRequest
1 голос
/ 21 марта 2012

У меня есть четко определенный контракт на обслуживание, который раскрывает множество методов. У нас есть типичная реализация этого контракта для службы, которая размещается в IIS 7 вместе с нашим приложением MVC.

Архитектура представляет собой типичное распределенное приложение с интерфейсом, определенным в базовой базовой библиотеке (которая перераспределяется), реализацией внутри независимой библиотеки служб и, наконец, приложением MVC, предоставляющим конечную точку для реализации (которая находится в библиотеке услуг).

Ситуация в настоящее время заключается в том, что один из этих существующих методов обслуживания должен возможно выполнять логический процесс, выполнение которого может занять до 10 минут. В обычном сценарии мы рассмотрели бы сервисы рабочих процессов, но рассматриваемый интерфейс хорошо используется, у нас есть набор модульных тестов для тестирования наших сервисов и т. Д., И мы действительно не можем уйти с этой реализацией, которая у нас есть.


Итак, мои вопросы -

  1. Возможно ли иметь независимый рабочий процесс, который может выполнять этот длительный процесс и вызывать его из нашей службы WCF?
  2. Если это так, как мне обеспечить, чтобы рабочий поток, выполняющий мою службу в IIS, оставался в живых в течение всего рабочего процесса?
  3. Наконец, клиенту не нужно ждать ответа от этой службы. Это метод огня и забыть. Может ли клиентский вызов завершиться немедленно, пока служба запускает рабочий процесс и ожидает его завершения?

1 Ответ

6 голосов
/ 21 марта 2012
  1. Конечно.В вашей службе WCF вы будете использовать WorkflowApplication для выполнения определения вашего рабочего процесса.Это позаботится о выполнении / отслеживании каждого экземпляра WF во время выполнения WF в определенных потоках времени выполнения WF (т. Е. Без блокировки потока ввода-вывода WCF).
  2. Здесь нет никаких гарантий.Если пул приложений дает сбой или планируется отключить из-за «неактивности», что приведет к прекращению любых рабочих процессов, которые все еще потенциально выполняются.Вам нужно будет использовать точки сохранения, чтобы в случае прекращения работы WF вы возобновили работу с предыдущих закладок.
  3. Да, сначала пометьте свой метод службы WCF с помощью [OperationContract (IsOneWay = true)] .Во-вторых, вы будете использовать экземпляр WorkflowApplication из 1, чтобы запустить WF с помощью async BeginRun, и, если вам нужно отслеживать завершение / ошибки в вашей службе WCF, вы можете зарегистрировать необходимые Aborted, Completed, *Обработчики 1015 *.

Вот очень простой пример:

[DataContract]
public class MyParametersDataContract
{
   [DataMember(Order=1, IsRequired=true)]
   public string SomeValue
   {
       get;
       set;
   }
}

public class IMyService
{
    [OperationContract(IsOneWay=true)]
    void DoSomething(MyParametersDataContract someParameters);
}

public class MyService : IMyService
{
     // Hold your WF definition in a static singleton to reduce overhead of activity realization
     public static readonly Lazy<MyFancyWorkflow> MyWorkflow = Lazy<MyFancyWorkflow>(() => new MyFancyWorkflow());

     public void DoSomething(MyParametersDataContract someParameters)
     {
         // Example of translating incoming parameters to WF args
         Dictionary<string, object> workflowInputArguments = new Dictionary<string, object>
         {
             { "SomeArgument", someParameters.SomeValue }
         };

         // Create a WFA instance for this request
         WorkflowApplication workflowApplication = new WorkflowApplication(MyService.MyWorkflow.Value, workflowInputArguments);

         // Example of hooking the completed action
         workflowApplication.Completed = (workflowCompletedArgs) =>
         {
             // do something when workflow has completed
         };

         // Invoke the running of the WF asynchronously
         Task.Factory.FromAsync(
                                workflowApplication.BeginRun,
                                workflowApplication.EndRun,
                                null)
                               .ContinueWith(runAntecdent =>
                               {
                                  // Observe/log any exception with starting the WF so it doesn't crash the process
                                  Trace.TraceWarning("WF failed to run: " + runAntecedent.Exception.ToString());
                               },
                               TaskContinuationOptions.OnlyOnFaulted);
     }
}
...