Aracılığıyla paylaş


WorkflowInvoker ve WorkflowApplication Kullanma

Windows Workflow Foundation (WF), iş akışlarını barındırmak için çeşitli yöntemler sağlar. WorkflowInvoker bir iş akışını bir yöntem çağrısıymış gibi çağırmak için basit bir yol sağlar ve yalnızca kalıcılık kullanmayan iş akışları için kullanılabilir. WorkflowApplication yaşam döngüsü olayları, yürütme denetimi, yer işareti yeniden başlatma ve kalıcılık bildirimini içeren iş akışlarını yürütmek için daha zengin bir model sağlar. WorkflowServiceHost mesajlaşma etkinlikleri için destek sağlar ve öncelikli olarak iş akışı hizmetleriyle birlikte kullanılır. Bu konu, ve WorkflowApplicationile WorkflowInvoker iş akışı barındırmayı tanıtır. ile WorkflowServiceHostiş akışları barındırma hakkında daha fazla bilgi için bkz . İş Akışı Hizmetlerine ve Barındırma İş Akışı Hizmetlerine Genel Bakış.

WorkflowInvoker kullanma

WorkflowInvoker bir iş akışını yöntem çağrısıymış gibi yürütmek için bir model sağlar. kullanarak WorkflowInvokerbir iş akışını çağırmak için yöntemini çağırın Invoke ve çağıracak iş akışının iş akışı tanımını geçirin. Bu örnekte, kullanılarak WorkflowInvokerbir WriteLine etkinlik çağrılır.

Activity wf = new WriteLine
{
    Text = "Hello World."
};

WorkflowInvoker.Invoke(wf);

kullanılarak WorkflowInvokerbir iş akışı çağrıldığında, iş akışı çağıran iş parçacığında yürütülür ve Invoke yöntem, boşta kalma süresi dahil olmak üzere iş akışı tamamlanana kadar engeller. İş akışının tamamlanması gereken zaman aşımı aralığını yapılandırmak için parametre alan TimeSpan aşırı yüklemelerden birini Invoke kullanın. Bu örnekte, bir iş akışı iki farklı zaman aşımı aralığıyla iki kez çağrılır. İlk iş akışı tamamlar, ancak ikincisi tamamlanmaz.

Activity wf = new Sequence()
{
    Activities =
    {
        new WriteLine()
        {
            Text = "Before the 1 minute delay."
        },
        new Delay()
        {
            Duration = TimeSpan.FromMinutes(1)
        },
        new WriteLine()
        {
            Text = "After the 1 minute delay."
        }
    }
};

// This workflow completes successfully.
WorkflowInvoker.Invoke(wf, TimeSpan.FromMinutes(2));

// This workflow does not complete and a TimeoutException
// is thrown.
try
{
    WorkflowInvoker.Invoke(wf, TimeSpan.FromSeconds(30));
}
catch (TimeoutException ex)
{
    Console.WriteLine(ex.Message);
}

Not

TimeoutException yalnızca zaman aşımı aralığı geçtiğinde ve iş akışı yürütme sırasında boşta kalırsa oluşturulur. İş akışı boşta kalmazsa, tamamlanması belirtilen zaman aşımı aralığından daha uzun süren bir iş akışı başarıyla tamamlanır.

WorkflowInvoker ayrıca invoke yönteminin zaman uyumsuz sürümlerini de sağlar. Daha fazla bilgi için bkz. InvokeAsync ve BeginInvoke.

İş Akışının Giriş Bağımsız Değişkenlerini Ayarlama

Veriler, iş akışının giriş bağımsız değişkenleriyle eşlenen bağımsız değişken adıyla anahtarlanan giriş parametreleri sözlüğü kullanılarak iş akışına geçirilebilir. Bu örnekte, bir WriteLine çağrılır ve bağımsız değişkeninin Text değeri giriş parametrelerinin sözlüğü kullanılarak belirtilir.

Activity wf = new WriteLine();

Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Text", "Hello World.");

WorkflowInvoker.Invoke(wf, inputs);

İş Akışının Çıkış Bağımsız Değişkenlerini Alma

bir iş akışının çıkış parametreleri, çağrısından Invokedöndürülen çıkışlar sözlüğü kullanılarak elde edilebilir. Aşağıdaki örnek, iki giriş bağımsız değişkeni ve iki çıkış bağımsız değişkeni olan tek Divide bir etkinlik içeren bir iş akışını çağırır. İş akışı çağrıldığında, her giriş bağımsız değişkeninin arguments değerlerini içeren ve bağımsız değişken adına göre anahtarlanan sözlük geçirilir. çağrısı Invoke döndürdüğünde, her çıkış bağımsız değişkeni sözlükte outputs döndürülür ve bağımsız değişken adıyla da anahtarlanır.

public sealed class Divide : CodeActivity
{
    [RequiredArgument]
    public InArgument<int> Dividend { get; set; }

    [RequiredArgument]
    public InArgument<int> Divisor { get; set; }

    public OutArgument<int> Remainder { get; set; }
    public OutArgument<int> Result { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        int quotient = Dividend.Get(context) / Divisor.Get(context);
        int remainder = Dividend.Get(context) % Divisor.Get(context);

        Result.Set(context, quotient);
        Remainder.Set(context, remainder);
    }
}
int dividend = 500;
int divisor = 36;

Dictionary<string, object> arguments = new Dictionary<string, object>();
arguments.Add("Dividend", dividend);
arguments.Add("Divisor", divisor);

IDictionary<string, object> outputs =
    WorkflowInvoker.Invoke(new Divide(), arguments);

Console.WriteLine("{0} / {1} = {2} Remainder {3}",
    dividend, divisor, outputs["Result"], outputs["Remainder"]);

İş akışı veya gibi öğesinden ActivityWithResulttüretiliyorsa ve iyi tanımlanmış Result çıkış bağımsız değişkenine ek olarak çıkış bağımsız değişkenleri varsa, ek bağımsız değişkenleri almak için genel olmayan bir aşırı yükleme Invoke CodeActivity<TResult> kullanılmalıdır.Activity<TResult> Bunu yapmak için içine geçirilen Invoke iş akışı tanımı türünde Activityolmalıdır. Bu örnekte Divide etkinlik, 'den CodeActivity<int>türetilir, ancak tek bir dönüş değeri yerine bağımsız değişken sözlüğü döndüren genel olmayan bir aşırı yüklemenin Invoke kullanılması için olarak Activity bildirilir.

public sealed class Divide : CodeActivity<int>
{
    public InArgument<int> Dividend { get; set; }
    public InArgument<int> Divisor { get; set; }
    public OutArgument<int> Remainder { get; set; }

    protected override int Execute(CodeActivityContext context)
    {
        int quotient = Dividend.Get(context) / Divisor.Get(context);
        int remainder = Dividend.Get(context) % Divisor.Get(context);

        Remainder.Set(context, remainder);

        return quotient;
    }
}
int dividend = 500;
int divisor = 36;

Dictionary<string, object> arguments = new Dictionary<string, object>();
arguments.Add("Dividend", dividend);
arguments.Add("Divisor", divisor);

Activity wf = new Divide();

IDictionary<string, object> outputs =
    WorkflowInvoker.Invoke(wf, arguments);

Console.WriteLine("{0} / {1} = {2} Remainder {3}",
    dividend, divisor, outputs["Result"], outputs["Remainder"]);

WorkflowApplication kullanma

WorkflowApplication iş akışı örneği yönetimi için zengin bir özellik kümesi sağlar. WorkflowApplication , çalışma zamanını kapsülleyen ve iş akışı örnekleri oluşturma ve yükleme, yaşam döngüsü olaylarını duraklatma ve devam ettirme, sonlandırma ve bildirim yöntemleri sağlayan, gerçek WorkflowInstanceöğesine iş parçacığı güvenli bir ara sunucu işlevi görür. kullanarak bir iş akışı WorkflowApplication WorkflowApplicationçalıştırmak için istediğiniz yaşam döngüsü olaylarına abone olun, iş akışını başlatın ve ardından bitmesini bekleyin. Bu örnekte, bir etkinlik içeren bir WriteLine iş akışı tanımı oluşturulur ve belirtilen iş akışı tanımı kullanılarak bir WorkflowApplication oluşturulur. Completed iş akışı tamamlandığında konağa bildirilmesi için işlenir, iş akışı çağrısıyla Runbaşlatılır ve ardından konak iş akışının tamamlanmasını bekler. İş akışı tamamlandığında, AutoResetEvent ayarlanır ve konak uygulaması aşağıdaki örnekte gösterildiği gibi yürütmeyi sürdürebilir.

AutoResetEvent syncEvent = new AutoResetEvent(false);

Activity wf = new WriteLine
{
    Text = "Hello World."
};

// Create the WorkflowApplication using the desired
// workflow definition.
WorkflowApplication wfApp = new WorkflowApplication(wf);

// Handle the desired lifecycle events.
wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e)
{
    syncEvent.Set();
};

// Start the workflow.
wfApp.Run();

// Wait for Completed to arrive and signal that
// the workflow is complete.
syncEvent.WaitOne();

WorkflowApplication Yaşam Döngüsü Olayları

ek olarakCompleted, bir iş akışı kaldırıldığında (), durdurulduğunda (AbortedUnloaded ), boşta kaldığında ( ve PersistableIdle) veya işlenmeyen bir özel durum oluştuğunda (IdleOnUnhandledException ) konak yazarlarına bildirilebilir. İş akışı uygulaması geliştiricileri, aşağıdaki örnekte gösterildiği gibi bu bildirimleri işleyebilir ve uygun eylemleri gerçekleştirebilir.

wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e)
{
    if (e.CompletionState == ActivityInstanceState.Faulted)
    {
        Console.WriteLine("Workflow {0} Terminated.", e.InstanceId);
        Console.WriteLine("Exception: {0}\n{1}",
            e.TerminationException.GetType().FullName,
            e.TerminationException.Message);
    }
    else if (e.CompletionState == ActivityInstanceState.Canceled)
    {
        Console.WriteLine("Workflow {0} Canceled.", e.InstanceId);
    }
    else
    {
        Console.WriteLine("Workflow {0} Completed.", e.InstanceId);

        // Outputs can be retrieved from the Outputs dictionary,
        // keyed by argument name.
        // Console.WriteLine("The winner is {0}.", e.Outputs["Winner"]);
    }
};

wfApp.Aborted = delegate (WorkflowApplicationAbortedEventArgs e)
{
    // Display the exception that caused the workflow
    // to abort.
    Console.WriteLine("Workflow {0} Aborted.", e.InstanceId);
    Console.WriteLine("Exception: {0}\n{1}",
        e.Reason.GetType().FullName,
        e.Reason.Message);
};

wfApp.Idle = delegate (WorkflowApplicationIdleEventArgs e)
{
    // Perform any processing that should occur
    // when a workflow goes idle. If the workflow can persist,
    // both Idle and PersistableIdle are called in that order.
    Console.WriteLine("Workflow {0} Idle.", e.InstanceId);
};

wfApp.PersistableIdle = delegate (WorkflowApplicationIdleEventArgs e)
{
    // Instruct the runtime to persist and unload the workflow.
    // Choices are None, Persist, and Unload.
    return PersistableIdleAction.Unload;
};

wfApp.Unloaded = delegate (WorkflowApplicationEventArgs e)
{
    Console.WriteLine("Workflow {0} Unloaded.", e.InstanceId);
};

wfApp.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
    // Display the unhandled exception.
    Console.WriteLine("OnUnhandledException in Workflow {0}\n{1}",
        e.InstanceId, e.UnhandledException.Message);

    Console.WriteLine("ExceptionSource: {0} - {1}",
        e.ExceptionSource.DisplayName, e.ExceptionSourceInstanceId);

    // Instruct the runtime to terminate the workflow.
    // Other choices are Abort and Cancel. Terminate
    // is the default if no OnUnhandledException handler
    // is present.
    return UnhandledExceptionAction.Terminate;
};

İş Akışının Giriş Bağımsız Değişkenlerini Ayarlama

Veriler, kullanılırken WorkflowInvokerverilerin geçirilme yöntemine benzer bir parametre sözlüğü kullanılarak başlatıldığında iş akışına geçirilebilir. Sözlükteki her öğe, belirtilen iş akışının giriş bağımsız değişkeniyle eşler. Bu örnekte, bir etkinlik içeren bir WriteLine iş akışı çağrılır ve Text bağımsız değişkeni giriş parametreleri sözlüğü kullanılarak belirtilir.

AutoResetEvent syncEvent = new AutoResetEvent(false);

Activity wf = new WriteLine();

// Create the dictionary of input parameters.
Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Text", "Hello World!");

// Create the WorkflowApplication using the desired
// workflow definition and dictionary of input parameters.
WorkflowApplication wfApp = new WorkflowApplication(wf, inputs);

// Handle the desired lifecycle events.
wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e)
{
    syncEvent.Set();
};

// Start the workflow.
wfApp.Run();

// Wait for Completed to arrive and signal that
// the workflow is complete.
syncEvent.WaitOne();

İş Akışının Çıkış Bağımsız Değişkenlerini Alma

bir iş akışı tamamlandığında, herhangi bir çıkış bağımsız değişkeni sözlüğe erişilerek işleyicide Completed WorkflowApplicationCompletedEventArgs.Outputs alınabilir. Aşağıdaki örnek kullanarak WorkflowApplicationbir iş akışı barındırıyor. Örnek WorkflowApplication , tek DiceRoll bir etkinlik içeren bir iş akışı tanımı kullanılarak oluşturulur. Etkinlikte DiceRoll zar atma işleminin sonuçlarını temsil eden iki çıkış bağımsız değişkeni vardır. İş akışı tamamlandığında, çıkışlar işleyicide Completed alınır.

public sealed class DiceRoll : CodeActivity
{
    public OutArgument<int> D1 { get; set; }
    public OutArgument<int> D2 { get; set; }

    static Random r = new Random();

    protected override void Execute(CodeActivityContext context)
    {
        D1.Set(context, r.Next(1, 7));
        D2.Set(context, r.Next(1, 7));
    }
}
// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(new DiceRoll());

// Subscribe to any desired workflow lifecycle events.
wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e)
{
    if (e.CompletionState == ActivityInstanceState.Faulted)
    {
        Console.WriteLine("Workflow {0} Terminated.", e.InstanceId);
        Console.WriteLine("Exception: {0}\n{1}",
            e.TerminationException.GetType().FullName,
            e.TerminationException.Message);
    }
    else if (e.CompletionState == ActivityInstanceState.Canceled)
    {
        Console.WriteLine("Workflow {0} Canceled.", e.InstanceId);
    }
    else
    {
        Console.WriteLine("Workflow {0} Completed.", e.InstanceId);

        // Outputs can be retrieved from the Outputs dictionary,
        // keyed by argument name.
        Console.WriteLine("The two dice are {0} and {1}.",
            e.Outputs["D1"], e.Outputs["D2"]);
    }
};

// Run the workflow.
wfApp.Run();

Not

WorkflowApplicationve WorkflowInvoker giriş bağımsız değişkenlerini içeren bir sözlük alın ve bağımsız değişkenlerden oluşan bir sözlük döndür.out Bu sözlük parametreleri, özellikleri ve dönüş değerleri türündedir IDictionary<string, object>. geçirilen sözlük sınıfının gerçek örneği uygulayan IDictionary<string, object>herhangi bir sınıf olabilir. Bu örneklerde Dictionary<string, object> kullanılır. Sözlükler hakkında daha fazla bilgi için bkz IDictionary<TKey,TValue> . ve Dictionary<TKey,TValue>.

Yer İşaretlerini Kullanarak Çalışan İş Akışına Veri Geçirme

Yer işaretleri, bir etkinliğin sürdürülmeyi pasif olarak bekleyebileceği mekanizmadır ve çalışan bir iş akışı örneğine veri geçirmeye yönelik bir mekanizmadır. Bir etkinlik veri bekliyorsa, aşağıdaki örnekte gösterildiği gibi bir oluşturabilir Bookmark ve sürdürülürken Bookmark çağrılacak bir geri çağırma yöntemi kaydedebilir.

public sealed class ReadLine : NativeActivity<string>
{
    [RequiredArgument]
    public InArgument<string> BookmarkName { get; set; }

    protected override void Execute(NativeActivityContext context)
    {
        // Create a Bookmark and wait for it to be resumed.
        context.CreateBookmark(BookmarkName.Get(context),
            new BookmarkCallback(OnResumeBookmark));
    }

    // NativeActivity derived activities that do asynchronous operations by calling
    // one of the CreateBookmark overloads defined on System.Activities.NativeActivityContext
    // must override the CanInduceIdle property and return true.
    protected override bool CanInduceIdle
    {
        get { return true; }
    }

    public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj)
    {
        // When the Bookmark is resumed, assign its value to
        // the Result argument.
        Result.Set(context, (string)obj);
    }

Yürütülürken, ReadLine etkinlik bir Bookmarkoluşturur, bir geri çağırma kaydeder ve ardından sürdürülmesini Bookmark bekler. Devam ettirildiğinde, ReadLine etkinlik ile geçirilen Bookmark verileri bağımsız değişkenine Result atar. Bu örnekte, kullanıcının adını toplamak ve konsol penceresinde görüntülemek için etkinliği kullanan ReadLine bir iş akışı oluşturulur.

Variable<string> name = new Variable<string>();

Activity wf = new Sequence
{
    Variables = { name },
    Activities =
     {
         new WriteLine
         {
             Text = "What is your name?"
         },
         new ReadLine
         {
             BookmarkName = "UserName",
             Result = new OutArgument<string>(name)
         },
         new WriteLine
         {
             Text = new InArgument<string>((env) =>
                 ("Hello, " + name.Get(env)))
         }
     }
};

// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);

// Workflow lifecycle events omitted except idle.
AutoResetEvent idleEvent = new AutoResetEvent(false);

wfApp.Idle = delegate (WorkflowApplicationIdleEventArgs e)
{
    idleEvent.Set();
};

// Run the workflow.
wfApp.Run();

// Wait for the workflow to go idle before gathering
// the user's input.
idleEvent.WaitOne();

// Gather the user's input and resume the bookmark.
// Bookmark resumption only occurs when the workflow
// is idle. If a call to ResumeBookmark is made and the workflow
// is not idle, ResumeBookmark blocks until the workflow becomes
// idle before resuming the bookmark.
BookmarkResumptionResult result = wfApp.ResumeBookmark("UserName",
    Console.ReadLine());

// Possible BookmarkResumptionResult values:
// Success, NotFound, or NotReady
Console.WriteLine("BookmarkResumptionResult: {0}", result);

ReadLine Etkinlik yürütülürken, bir Bookmark adlandırılmış UserName oluşturur ve yer işaretinin sürdürülmesini bekler. Konak istenen verileri toplar ve ardından öğesini sürdürür Bookmark. İş akışı devam eder, adı görüntüler ve ardından tamamlar.

Konak uygulaması, etkin yer işaretleri olup olmadığını belirlemek için iş akışını inceleyebilir. Bunu bir örneğin yöntemini WorkflowApplication çağırarak GetBookmarks veya işleyicisinde Idle inceleyerek WorkflowApplicationIdleEventArgs yapabilir.

Aşağıdaki kod örneği, yer işareti sürdürülmeden önce etkin yer işaretlerinin numaralandırılmış olması dışında önceki örneğe benzer. İş akışı başlatılır ve iş akışı oluşturulduktan Bookmark ve boşta GetBookmarks kaldığında çağrılır. İş akışı tamamlandığında konsolda aşağıdaki çıkış görüntülenir.

Adınız ne?
BookmarkName: UserName - OwnerDisplayName: ReadLineSteveHello, Steve

Variable<string> name = new Variable<string>();

Activity wf = new Sequence
{
    Variables = { name },
    Activities =
     {
         new WriteLine
         {
             Text = "What is your name?"
         },
         new ReadLine
         {
             BookmarkName = "UserName",
             Result = new OutArgument<string>(name)
         },
         new WriteLine
         {
             Text = new InArgument<string>((env) =>
                 ("Hello, " + name.Get(env)))
         }
     }
};

// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);

// Workflow lifecycle events omitted except idle.
AutoResetEvent idleEvent = new AutoResetEvent(false);

wfApp.Idle = delegate (WorkflowApplicationIdleEventArgs e)
{
    // You can also inspect the bookmarks from the Idle handler
    // using e.Bookmarks

    idleEvent.Set();
};

// Run the workflow.
wfApp.Run();

// Wait for the workflow to go idle and give it a chance
// to create the Bookmark.
idleEvent.WaitOne();

// Inspect the bookmarks
foreach (BookmarkInfo info in wfApp.GetBookmarks())
{
    Console.WriteLine("BookmarkName: {0} - OwnerDisplayName: {1}",
        info.BookmarkName, info.OwnerDisplayName);
}

// Gather the user's input and resume the bookmark.
wfApp.ResumeBookmark("UserName", Console.ReadLine());

Aşağıdaki kod örneği, bir WorkflowApplication örneğin işleyicisine Idle geçirilen öğesini incelerWorkflowApplicationIdleEventArgs. Bu örnekte, boşta kalan iş akışında adlı bir etkinlik tarafından sahip olunan adlı EnterGuessbir iş ReadIntakışı vardırBookmark. Bu kod örneği, Başlarken Öğreticisi'nin bir parçası olan Nasıl Yapılır: İş Akışı Çalıştırma'yı temel alır. Bu adımdaki Idle işleyici bu örnekteki kodu içerecek şekilde değiştirilirse aşağıdaki çıkış görüntülenir.

BookmarkName: EnterGuess - OwnerDisplayName: ReadInt

wfApp.Idle = delegate (WorkflowApplicationIdleEventArgs e)
{
    foreach (BookmarkInfo info in e.Bookmarks)
    {
        Console.WriteLine("BookmarkName: {0} - OwnerDisplayName: {1}",
            info.BookmarkName, info.OwnerDisplayName);
    }

    idleEvent.Set();
};

Özet

WorkflowInvoker iş akışlarını çağırmak için basit bir yol sağlar ve bir iş akışının başlangıcında verileri geçirmek ve tamamlanmış bir iş akışından veri ayıklamak için yöntemler sağlasa da, burada kullanılabilecek daha karmaşık senaryolar WorkflowApplication sağlamaz.