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ının bildirimi, yürütme kontrolü, yer işareti devam ettirme ve kalıcılık 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, WorkflowInvoker ve WorkflowApplication ile iş akışı barındırmayı tanıtır. İş akışları barındırma hakkında daha fazla bilgi için WorkflowServiceHost bölümüne, İş Akışı Hizmetleri ve Barındırma İş Akışı Hizmetlerine Genel Bakış sayfalarına bakın.

WorkflowInvoker kullanma

WorkflowInvoker bir iş akışını yöntem çağrısıymış gibi yürütmek için bir model sağlar. Bir iş akışını çağırmak için, WorkflowInvoker kullanarak Invoke yöntemini çağırın ve başlatılacak iş akışının tanımını gönderin. Bu örnekte, bir WriteLine etkinliği WorkflowInvoker kullanılarak çağrılır.

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

WorkflowInvoker.Invoke(wf);

Bir iş akışı WorkflowInvoker kullanılarak çağrıldığında, iş akışı çağıran iş parçacığında yürütülür ve Invoke yöntemi, 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 Invoke aşırı yüklemelerden birini TimeSpan 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);
}

Uyarı

TimeoutException, yalnızca zaman aşımı aralığı dolduğunda ve iş akışı yürütme sırasında boşta kaldığında tetiklenir. İş 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ş Parametrelerini Ayarlama

Veriler, iş akışının giriş argümanlarına eşlenmiş olan, argüman adı anahtarıyla belirtilen giriş parametreleri sözlüğü kullanılarak iş akışına aktarılabilir. 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ış Argümanlarını Alma

Çıkış sözlüğü kullanılarak bir iş akışının çıkış parametreleri, Invoke çağrısından döndürülen sonuçlardan 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 değerlerini içeren ve bağımsız değişken adına göre anahtarlanan arguments sözlüğü iletilir. "Invoke çağrısı döndüğünde, her çıkış bağımsız değişkeni outputs sözlüğünde bağımsız değişken adıyla anahtarlanarak döndürülü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($"{dividend} / {divisor} = {outputs["Result"]} Remainder {outputs["Remainder"]}");

İş akışı ActivityWithResult gibi CodeActivity<TResult> veya Activity<TResult> öğesinden türetiliyorsa ve iyi tanımlanmış Result çıkış bağımsız değişkenine ek olarak başka çıkış bağımsız değişkenleri varsa, ek bağımsız değişkenleri almak için Invoke'ün genel olmayan bir aşırı yüklemesi kullanılmalıdır. Bunu yapmak için içine geçirilen Invoke iş akışı tanımı türünde Activityolmalıdır. Bu örnekte Divide etkinlik CodeActivity<int>'den türetilir, ancak bağımsız değişken sözlüğü döndüren ve tek bir geri dönüş değeri sağlamayan genel olmayan bir aşırı yüklemenin Activity kullanılması için Invoke olarak 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($"{dividend} / {divisor} = {outputs["Result"]} Remainder {outputs["Remainder"]}");

WorkflowApplication kullanma

WorkflowApplication iş akışı örneği yönetimi için zengin bir özellik kümesi sağlar. WorkflowApplication, gerçek WorkflowInstance için iş parçacığı güvenli bir ara sunucu görevi görür; bu, çalışma zamanını kapsüller ve iş akışı örnekleri oluşturmak, yüklemek, duraklatmak, devam ettirmek, sonlandırmak ve yaşam döngüsü olaylarını bildirmek için yöntemler sağlar. WorkflowApplication kullanarak bir iş akışını çalıştırmak için, WorkflowApplication oluşturun, 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ışı bir çağrıyla Run baş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ı

tr-TR: Completed'ya ek olarak, bir iş akışı kaldırıldığında (Unloaded), durdurulduğunda (Aborted), boşta kaldığında (Idle ve PersistableIdle) veya işlenmeyen bir özel durum oluştuğunda (OnUnhandledException), konak yazarlarına bildirimde bulunulabilir. İş 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 {e.InstanceId} Terminated.");
        Console.WriteLine($"Exception: {e.TerminationException.GetType().FullName}\n{e.TerminationException.Message}");
    }
    else if (e.CompletionState == ActivityInstanceState.Canceled)
    {
        Console.WriteLine($"Workflow {e.InstanceId} Canceled.");
    }
    else
    {
        Console.WriteLine($"Workflow {e.InstanceId} Completed.");

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

wfApp.Aborted = delegate (WorkflowApplicationAbortedEventArgs e)
{
    // Display the exception that caused the workflow
    // to abort.
    Console.WriteLine($"Workflow {e.InstanceId} Aborted.");
    Console.WriteLine($"Exception: {e.Reason.GetType().FullName}\n{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 {e.InstanceId} Idle.");
};

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 {e.InstanceId} Unloaded.");
};

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

    Console.WriteLine($"ExceptionSource: {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ş Parametrelerini Ayarlama

Veriler, WorkflowInvoker kullanılırken verilerin geçirilme şekline benzer bir parametre sözlüğü kullanılarak iş akışı başlatıldığında iş akışına geçirilebilir. Belirtilen iş akışının her bir giriş bağımsız değişkeni, sözlükteki bir öğeyle eşleşir. 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ış Argümanlarını Alma

Bir iş akışı tamamlandığında, herhangi bir çıkış bağımsız değişkeni Completed işleyicisinde WorkflowApplicationCompletedEventArgs.Outputs sözlüğüne erişilerek alınabilir. Aşağıdaki örnek, WorkflowApplication kullanarak bir iş akışını 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ış argümanı bulunmaktadır. İş akışı tamamlandığında, çıktılar Completed işleyicisinde elde edilir.

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 {e.InstanceId} Terminated.");
        Console.WriteLine($"Exception: {e.TerminationException.GetType().FullName}\n{e.TerminationException.Message}");
    }
    else if (e.CompletionState == ActivityInstanceState.Canceled)
    {
        Console.WriteLine($"Workflow {e.InstanceId} Canceled.");
    }
    else
    {
        Console.WriteLine($"Workflow {e.InstanceId} Completed.");

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

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

Uyarı

WorkflowApplication ve WorkflowInvoker, giriş argümanlarını içeren bir sözlük alır ve out argümanlarını içeren bir sözlük döndürür. 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, IDictionary<string, object> uygulayan 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 Bookmark oluşturabilir ve Bookmark sürdürülmesi esnasında çağrılacak bir geri çağırma yöntemi bu esnada 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 Bookmark oluşturur, bir geri çağırma kaydeder ve ardından Bookmark'nin devam etmesini bekler. Sürdürülmeye devam edildiğinde, ReadLine etkinliği, Bookmark ile iletilen verileri Result bağımsız değişkenine 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: {result}");

ReadLine etkinliği yürütüldüğünde, Bookmark isimli bir UserName oluşturur ve yer işaretinin devam etmesini bekler. Sunucu istenen verileri toplar ve ardından Bookmark devam eder. İş akışı devam eder, adı görüntüler ve ardından tamamlar.

Ana uygulama, etkin işaretçiler olup olmadığını belirlemek için iş akışını inceleyebilir. Bir GetBookmarks örneğinin WorkflowApplication yöntemini çağırarak veya WorkflowApplicationIdleEventArgs işleyicisindeki Idle'yi inceleyerek bunu 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 Bookmark oluşturulduktan sonra iş akışı boşta kaldığında, GetBookmarks ç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: {info.BookmarkName} - OwnerDisplayName: {info.OwnerDisplayName}");
}

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

Aşağıdaki kod örneği, bir WorkflowApplicationIdleEventArgs örneğinin işleyicisine Idle ile geçirilen WorkflowApplication öğesini inceler. Bu örnekte boşta kalan iş akışı, adı Bookmark olan ve EnterGuess adlı bir etkinlik tarafından yönetilen ReadInt içerir. Bu kod örneği, Başlarken Öğreticisi'nin bir parçası olan Nasıl Yapılır: İş Akışı Çalıştırma üzerine kuruludur. 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: {info.BookmarkName} - OwnerDisplayName: {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.