Aracılığıyla paylaş


Ücret

Windows Workflow Foundation'da (WF) telafi, daha sonra bir hata oluştuğunda daha önce tamamlanan çalışmanın geri alınabileceği veya telafi edilebileceği mekanizmadır (uygulama tarafından tanımlanan mantık uyarınca). Bu bölümde, iş akışlarında dengelemenin nasıl kullanılacağı açıklanmaktadır.

Ücret ve İşlemler karşılaştırması

İşlem, birden çok işlemi tek bir iş biriminde birleştirmenizi sağlar. İşlem kullanmak, uygulamanıza işlem işleminin herhangi bir bölümünde hata oluşması durumunda işlem içinden yürütülen tüm değişiklikleri durdurma (geri alma) olanağı sağlar. Ancak, işlemin uzun sürmesi durumunda işlemleri kullanmak uygun olmayabilir. Örneğin, bir seyahat planlama uygulaması iş akışı olarak uygulanır. İş akışının adımları bir uçuş rezervasyonundan, yönetici onayını beklemekten ve ardından uçuşun ücretini ödemekten oluşabilir. Bu işlem birçok gün sürebilir ve uçuş için rezervasyon yapma ve ödeme adımlarının aynı işlem içinde yer alması pratik değildir. Böyle bir senaryoda, işlemenin devamında bir hata olması durumunda iş akışının rezervasyon adımını geri almak için tazminat kullanılabilir.

Uyarı

Bu konu iş akışlarında telafiyi kapsar. İş akışlarındaki işlemler hakkında daha fazla bilgi için bkz. İşlemler ve TransactionScope. İşlemler hakkında daha fazla bilgi için bkz System.Transactions . ve System.Transactions.Transaction.

CompensableActivity Kullanma

CompensableActivity WF'deki temel dengeleme etkinliğidir. Telafi edilmesi gerekebilecek işleri gerçekleştiren tüm etkinlikler bir Bodyın CompensableActivity içine yerleştirilir. Bu örnekte, bir uçuş satın alma işleminin rezervasyon adımı bir Body ve CompensableActivity içine yerleştirilir, rezervasyonun iptali ise CompensationHandler içine yerleştirilir. İş akışında öğesinin CompensableActivity hemen ardından, yönetici onayı bekleyen ve ardından uçuşun satın alma adımını tamamlayan iki etkinlik vardır. Eğer bir hata koşulu CompensableActivity başarıyla tamamlandıktan sonra iş akışının iptal edilmesine sebep olursa, işleyicideki CompensationHandler etkinlikler zamanlanır ve uçuş iptal edilir.

Activity wf = new Sequence()
{
    Activities =
    {
        new CompensableActivity
        {
            Body = new ReserveFlight(),
            CompensationHandler = new CancelFlight()
        },
        new ManagerApproval(),
        new PurchaseFlight()
    }
};

Aşağıdaki örnek, XAML'deki iş akışıdır.

<Sequence
   xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
   xmlns:c="clr-namespace:CompensationExample;assembly=CompensationExample"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <CompensableActivity>
    <CompensableActivity.Result>
      <OutArgument
         x:TypeArguments="CompensationToken" />
    </CompensableActivity.Result>
    <CompensableActivity.CompensationHandler>
      <c:CancelFlight />
    </CompensableActivity.CompensationHandler>
    <c:ReserveFlight />
  </CompensableActivity>
  <c:ManagerApproval />
  <c:PurchaseFlight />
</Sequence>

İş akışı çağrıldığında konsolda aşağıdaki çıkış görüntülenir.

ReserveFlight: Bilet ayrılmıştır.ManagerApproval: Yönetici onayı alındı.PurchaseFlight: Bilet satın alınır.İş akışı şu durumla başarıyla tamamlandı: Kapatıldı.

Uyarı

Bu konudaki örnek etkinlikler, telafi gerçekleştiğinde etkinliklerin yürütülme sırasını anlamaya yardımcı olmak için adlarını ve amaçlarını konsolda görüntüleme gibi ReserveFlight.

Varsayılan İş Akışı Telafisi

Varsayılan olarak, iş akışı iptal edilirse, telafi mantığı tamamen başarıyla tamamlanmış ve henüz onaylanmamış veya telafi edilmeyen tüm telafi edilebilir etkinlikler için çalıştırılır.

Uyarı

Bir CompensableActivityonaylandığında, etkinliğin tazminatı artık talep edilemez. Onay işlemi bu bölümün ilerleyen bölümlerinde açıklanmıştır.

Bu örnekte, uçuş rezerve edildikten sonra, ancak yönetici onayı adımından önce bir istisna atılır.

Activity wf = new Sequence()
{
    Activities =
    {
        new CompensableActivity
        {
            Body = new ReserveFlight(),
            CompensationHandler = new CancelFlight()
        },
        new SimulatedErrorCondition(),
        new ManagerApproval(),
        new PurchaseFlight()
    }
};

Bu örnek, XAML'deki iş akışıdır.

<Sequence
   xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
   xmlns:c="clr-namespace:CompensationExample;assembly=CompensationExample"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <CompensableActivity>
    <CompensableActivity.Result>
      <OutArgument
         x:TypeArguments="CompensationToken" />
    </CompensableActivity.Result>
    <CompensableActivity.CompensationHandler>
      <c:CancelFlight />
    </CompensableActivity.CompensationHandler>
    <c:ReserveFlight />
  </CompensableActivity>
  <c:SimulatedErrorCondition />
  <c:ManagerApproval />
  <c:PurchaseFlight />
</Sequence>
AutoResetEvent syncEvent = new AutoResetEvent(false);
WorkflowApplication wfApp = new WorkflowApplication(wf);

wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
{
    if (e.TerminationException != null)
    {
        Console.WriteLine($"""
        Workflow terminated with exception:
        {e.TerminationException.GetType().FullName}: {e.TerminationException.Message}
        """);
    }
    else
    {
        Console.WriteLine($"Workflow completed successfully with status: {e.CompletionState}.");
    }

    syncEvent.Set();
};

wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
    Console.WriteLine($"""
    Workflow Unhandled Exception:
    {e.UnhandledException.GetType().FullName}: {e.UnhandledException.Message}
    """);

    return UnhandledExceptionAction.Cancel;
};

wfApp.Run();
syncEvent.WaitOne();

İş akışı çağrıldığında, benzetilmiş hata durumu hatası OnUnhandledException içindeki konak uygulama tarafından işlenir, iş akışı iptal edilir ve dengeleme mantığı çağrılır.

ReserveFlight: Bilet ayrılmıştır.SimulatedErrorCondition: ApplicationException Oluşturma.İş Akışı İşlenmeyen Özel Durum:System.ApplicationException: İş akışında sanal hata koşulu.CancelFlight: Bilet iptal edildi.İş akışı şu durumda başarıyla tamamlandı: İptal edildi.

İptal ve Telafi Edilebilen Etkinlik

içindeki etkinlikleri BodyCompensableActivity tamamlanmamışsa ve etkinlik iptal edilirse içindeki etkinlikler CancellationHandler yürütülür.

Uyarı

CancellationHandler, Body içindeki CompensableActivity'deki etkinlikler tamamlanmadığı ve etkinlik iptal edildiği takdirde yalnızca çağrılır. CompensationHandler yalnızca BodyCompensableActivity içindeki etkinliklerin başarıyla tamamlanması ve daha sonra bu etkinliklerde telafinin çağrılması durumunda yürütülür.

, CancellationHandler iş akışı yazarlarına uygun iptal mantığını sağlama fırsatı verir. Aşağıdaki örnekte, Body sırasında bir istisna oluşturulur ve ardından CancellationHandler çağrılır.

Activity wf = new Sequence()
{
    Activities =
    {
        new CompensableActivity
        {
            Body = new Sequence
            {
                Activities =
                {
                    new ChargeCreditCard(),
                    new SimulatedErrorCondition(),
                    new ReserveFlight()
                }
            },
            CompensationHandler = new CancelFlight(),
            CancellationHandler = new CancelCreditCard()
        },
        new ManagerApproval(),
        new PurchaseFlight()
    }
};

Bu örnek, XAML'deki iş akışıdır

<Sequence
   xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
   xmlns:c="clr-namespace:CompensationExample;assembly=CompensationExample"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <CompensableActivity>
    <CompensableActivity.Result>
      <OutArgument
         x:TypeArguments="CompensationToken" />
    </CompensableActivity.Result>
    <Sequence>
      <c:ChargeCreditCard />
      <c:SimulatedErrorCondition />
      <c:ReserveFlight />
    </Sequence>
    <CompensableActivity.CancellationHandler>
      <c:CancelCreditCard />
    </CompensableActivity.CancellationHandler>
    <CompensableActivity.CompensationHandler>
      <c:CancelFlight />
    </CompensableActivity.CompensationHandler>
  </CompensableActivity>
  <c:ManagerApproval />
  <c:PurchaseFlight />
</Sequence>

İş akışı çağrıldığında, sanal hata koşulu içindeki özel durum OnUnhandledException konak uygulaması tarafından işlenir, iş akışı iptal edilir ve CompensableActivity iptal mantığı çağrılır. Bu örnekte, ücretlendirme mantığının ve iptal mantığının farklı hedefleri vardır. Body İşlem başarıyla tamamlanırsa, kredi kartından ücret tahsil edildiği ve uçuş rezervasyonu olduğu anlamına gelir, bu nedenle tazminat her iki adımı da geri almalıdır. (Bu örnekte, uçuşu iptal etmek kredi kartı ücretlerini otomatik olarak iptal eder.) Ancak, CompensableActivity iptal edilirse, bu Body'in tamamlanmadığı anlamına gelir ve bu durumda CancellationHandler mantığının iptal işlemini en iyi şekilde nasıl ele alacağını belirleyebilmesi gerekir. Bu örnekte, CancellationHandler kredi kartı ücretini iptal eder, ancak içindeki ReserveFlightson etkinlik olduğundanBody, uçuşu iptal etmeye çalışmaz. Eğer ReserveFlightBody içindeki son etkinlik olsaydı ve başarıyla tamamlanmış olsaydı, Body da tamamlanmış olurdu ve iptal mümkün olmazdı.

ChargeCreditCard: Uçuş için kredi kartı ücreti alın.SimulatedErrorCondition: ApplicationException Oluşturma.İş Akışı İşlenmeyen Özel Durum:System.ApplicationException: İş akışında sanal hata koşulu.CancelCreditCard: Kredi kartı ücretlerini iptal edin.İş akışı şu durumda başarıyla tamamlandı: İptal edildi. İptal hakkında daha fazla bilgi için bkz. İptal.

Telafi Etkinliğini Kullanarak Açık Dengeleme

Önceki bölümde örtük telafi kapsamına alınmıştır. Örtük telafi basit senaryolar için uygun olabilir, ancak telafi işlemenin Compensate zamanlaması üzerinde daha açık bir kontrol gerekiyorsa, bu faaliyet kullanılabilir. Tazminat sürecini Compensate etkinliği ile başlatmak için, tazminat talep edilen CompensationTokenCompensableActivity kullanılır. Etkinlik Compensate , onaylanmamış veya tazmin edilmeyen herhangi bir tamamlanmada CompensableActivity telafiyi başlatmak için kullanılabilir. Örneğin, bir Compensate etkinlik bir etkinliğin Catches bölümünde veya tamamlandıktan sonra TryCatch herhangi bir CompensableActivity zaman kullanılabilir. Bu örnekte, Compensate etkinliği, Catches bölümünde bir TryCatch etkinliğinde, CompensableActivity öğesinin eylemini tersine çevirmek için kullanılır.

Variable<CompensationToken> token1 = new Variable<CompensationToken>
{
    Name = "token1",
};

Activity wf = new TryCatch()
{
    Variables =
    {
        token1
    },
    Try = new Sequence
    {
        Activities =
        {
            new CompensableActivity
            {
                Body = new ReserveFlight(),
                CompensationHandler = new CancelFlight(),
                ConfirmationHandler = new ConfirmFlight(),
                Result = token1
            },
            new SimulatedErrorCondition(),
            new ManagerApproval(),
            new PurchaseFlight()
        }
    },
    Catches =
    {
        new Catch<ApplicationException>()
        {
            Action = new ActivityAction<ApplicationException>()
            {
                Handler = new Compensate()
                {
                    Target = token1
                }
            }
        }
    }
};

Bu örnek, XAML'deki iş akışıdır.

<TryCatch
   xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
   xmlns:c="clr-namespace:CompensationExample;assembly=CompensationExample"
   xmlns:s="clr-namespace:System;assembly=mscorlib"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <TryCatch.Variables>
    <Variable
       x:TypeArguments="CompensationToken"
       x:Name="__ReferenceID0"
       Name="token1" />
  </TryCatch.Variables>
  <TryCatch.Try>
    <Sequence>
      <CompensableActivity>
        <CompensableActivity.Result>
          <OutArgument
             x:TypeArguments="CompensationToken">
            <VariableReference
               x:TypeArguments="CompensationToken"
               Variable="{x:Reference __ReferenceID0}">
              <VariableReference.Result>
                <OutArgument
                   x:TypeArguments="Location(CompensationToken)" />
              </VariableReference.Result>
            </VariableReference>
          </OutArgument>
        </CompensableActivity.Result>
        <CompensableActivity.CompensationHandler>
          <c:CancelFlight />
        </CompensableActivity.CompensationHandler>
        <CompensableActivity.ConfirmationHandler>
          <c:ConfirmFlight />
        </CompensableActivity.ConfirmationHandler>
        <c:ReserveFlight />
      </CompensableActivity>
      <c:SimulatedErrorCondition />
      <c:ManagerApproval />
      <c:PurchaseFlight />
    </Sequence>
  </TryCatch.Try>
  <TryCatch.Catches>
    <Catch
       x:TypeArguments="s:ApplicationException">
      <ActivityAction
         x:TypeArguments="s:ApplicationException">
        <Compensate>
          <Compensate.Target>
            <InArgument
               x:TypeArguments="CompensationToken">
              <VariableValue
                 x:TypeArguments="CompensationToken"
                 Variable="{x:Reference __ReferenceID0}">
                <VariableValue.Result>
                  <OutArgument
                     x:TypeArguments="CompensationToken" />
                </VariableValue.Result>
              </VariableValue>
            </InArgument>
          </Compensate.Target>
        </Compensate>
      </ActivityAction>
    </Catch>
  </TryCatch.Catches>
</TryCatch>

İş akışı çağrıldığında konsolda aşağıdaki çıkış görüntülenir.

ReserveFlight: Bilet ayrılmıştır.SimulatedErrorCondition: ApplicationException Oluşturma.CancelFlight: Bilet iptal edildi.İş akışı şu durumla başarıyla tamamlandı: Kapatıldı.

Telafiyi Onaylama

Varsayılan olarak, telafi edilebilir etkinlikler tamamlandıktan sonra her zaman telafi edilebilir. Bazı senaryolarda bu uygun olmayabilir. Önceki örnekte bileti ayırmanın karşılığı rezervasyonu iptal etmekti. Ancak, uçuş tamamlandıktan sonra bu telafi adımı artık geçerli değildir. Telafi edilebilir bir etkinliğin onaylanması, ConfirmationHandler tarafından belirtilen etkinliği çağırır. Bunun için olası bir kullanım, tazminatı gerçekleştirmek için gerekli olan tüm kaynakların serbest bırakılmasına izin vermektir. Telafi edilebilir bir etkinlik onaylandıktan sonra telafi edilmesi mümkün değildir ve bu denenirse bir InvalidOperationException özel durum oluşturulur. Bir iş akışı başarıyla tamamlandığında, başarıyla tamamlanan tüm onaylanmamış ve telafi edilemeyen telafi edilebilir etkinlikler, tamamlanma sırasının tersine doğrulanır. Bu örnekte uçuş ayrılmış, satın alınmış ve tamamlanmış ve ardından telafi edilebilir etkinlik onaylanmıştır. bir CompensableActivityonaylamak için etkinliğini kullanın Confirm ve onaylayacak öğesini CompensationToken belirtinCompensableActivity.

Variable<CompensationToken> token1 = new Variable<CompensationToken>
{
    Name = "token1",
};

Activity wf = new Sequence()
{
    Variables =
    {
        token1
    },
    Activities =
    {
        new CompensableActivity
        {
            Body = new ReserveFlight(),
            CompensationHandler = new CancelFlight(),
            ConfirmationHandler = new ConfirmFlight(),
            Result = token1
        },
        new ManagerApproval(),
        new PurchaseFlight(),
        new TakeFlight(),
        new Confirm()
        {
            Target = token1
        }
    }
};

Bu örnek, XAML'deki iş akışıdır.

<Sequence
   xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
   xmlns:c="clr-namespace:CompensationExample;assembly=CompensationExample"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Sequence.Variables>
    <x:Reference>__ReferenceID0</x:Reference>
  </Sequence.Variables>
  <CompensableActivity>
    <CompensableActivity.Result>
      <OutArgument
         x:TypeArguments="CompensationToken">
        <VariableReference
           x:TypeArguments="CompensationToken">
          <VariableReference.Result>
            <OutArgument
               x:TypeArguments="Location(CompensationToken)" />
          </VariableReference.Result>
          <VariableReference.Variable>
            <Variable
               x:TypeArguments="CompensationToken"
               x:Name="__ReferenceID0"
               Name="token1" />
          </VariableReference.Variable>
        </VariableReference>
      </OutArgument>
    </CompensableActivity.Result>
    <CompensableActivity.CompensationHandler>
      <c:CancelFlight />
    </CompensableActivity.CompensationHandler>
    <CompensableActivity.ConfirmationHandler>
      <c:ConfirmFlight />
    </CompensableActivity.ConfirmationHandler>
    <c:ReserveFlight />
  </CompensableActivity>
  <c:ManagerApproval />
  <c:PurchaseFlight />
  <c:TakeFlight />
  <Confirm>
    <Confirm.Target>
      <InArgument
         x:TypeArguments="CompensationToken">
        <VariableValue
           x:TypeArguments="CompensationToken"
           Variable="{x:Reference __ReferenceID0}">
          <VariableValue.Result>
            <OutArgument
               x:TypeArguments="CompensationToken" />
          </VariableValue.Result>
        </VariableValue>
      </InArgument>
    </Confirm.Target>
  </Confirm>
</Sequence>

İş akışı çağrıldığında konsolda aşağıdaki çıkış görüntülenir.

ReserveFlight: Bilet ayrılmıştır.ManagerApproval: Yönetici onayı alındı.PurchaseFlight: Bilet satın alınır.TakeFlight: Uçuş tamamlandı.ConfirmFlight: Uçuş alındı, telafisi mümkün değil.İş akışı şu durumla başarıyla tamamlandı: Kapatıldı.

Telafi Etkinliklerini İç İçe Geçirme

birCompensableActivity, başka bir Bodyöğesinin CompensableActivity bölümüne yerleştirilebilir. CompensableActivity, başka bir CompensableActivity işleyicisine yerleştirilemeyebilir. Bir ebeveynin sorumluluğundadır ki, iptal edildiğinde, onaylandığında veya telafi edildiğinde, başarıyla tamamlanmış ve henüz onaylanmamış veya telafi edilmemiş tüm alt telafi edilebilir etkinlikler ebeveyn iptali, onayı veya telafisi tamamlanmadan önce onaylanmalı veya telafi edilmelidir. Bu açıkça modellenmemişse, üst öğe CompensableActivity iptal veya telafi sinyalini aldığında alt telafi edilebilir etkinlikleri örtük olarak telafi eder. Ebeveyn onay sinyalini aldıysa ebeveyn, alt telafi edilebilir etkinlikleri örtük olarak onaylar. İptal, onay veya telafi işlemleri işleme mantığı açıkça üst CompensableActivity öğesinin işleyicisinde modellenirse, açıkça işlenmemiş tüm alt öğeler örtük olarak onaylanır.

Ayrıca bkz.