Maaş
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ş uzun süre çalışıyorsa 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 aynı işleme katılmak için uçuş için rezervasyon ve ödeme adımları için 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.
Not
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 içine CompensableActivityyerleştirilirBody. Bu örnekte, bir uçuş satın alma işleminin rezervasyon adımı a içine, BodyCompensableActivity rezervasyonun iptali ise içine CompensationHandleryerleş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. Bir hata koşulu iş akışının başarıyla tamamlandıktan sonra iptal edilmesine CompensableActivity neden 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ı.
Not
Bu konudaki örnek etkinlikler, dengeleme gerçekleştiğinde etkinliklerin yürütülecek sırasını göstermeye 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.
Not
onaylandığında CompensableActivity, etkinliğin telafisi artık çağrılamamalıdır. 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 özel durum oluşturulur.
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:\n{0}: {1}",
e.TerminationException.GetType().FullName,
e.TerminationException.Message);
}
else
{
Console.WriteLine("Workflow completed successfully with status: {0}.",
e.CompletionState);
}
syncEvent.Set();
};
wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
Console.WriteLine("Workflow Unhandled Exception:\n{0}: {1}",
e.UnhandledException.GetType().FullName,
e.UnhandledException.Message);
return UnhandledExceptionAction.Cancel;
};
wfApp.Run();
syncEvent.WaitOne();
İş akışı çağrıldığında, sanal hata koşulu özel durumu içindeki konak uygulama OnUnhandledExceptiontarafı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.
Not
CancellationHandler yalnızca içindeki etkinliklerin BodyCompensableActivity tamamlanmaması ve etkinliğin iptal edilmiş olması durumunda çağrılır. CompensationHandler yalnızca içindeki etkinliklerin BodyCompensableActivity başarıyla tamamlanması ve daha sonra etkinlikte telafinin çağrılmış olması durumunda yürütülür.
, CancellationHandler iş akışı yazarlarına uygun iptal mantığını sağlama fırsatı verir. Aşağıdaki örnekte, yürütme Bodysırasında bir özel durum 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 özel durumu içindeki OnUnhandledExceptionkonak uygulaması tarafından işlenir, iş akışı iptal edilir ve iptal mantığı CompensableActivity ç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, iptal edilirse CompensableActivity , bu tamamlanmadığı anlamına gelir Body ve bu nedenle mantığının CancellationHandler iptal işlemini en iyi şekilde nasıl gerçekleştireceğini belirleyebilmesi gerekir. Bu örnekte, CancellationHandler kredi kartı ücretini iptal eder, ancak içindeki Bodyson etkinlik olduğundanReserveFlight
, uçuşu iptal etmeye çalışmaz. içindeki son etkinlik BodyolduğundanReserveFlight
, başarıyla tamamlamış Body olsaydı işlemi tamamlanırdı 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 ücret işlemenin Compensate zamanlanması üzerinde daha açık bir denetim gerekiyorsa etkinlik kullanılabilir. Ücretlendirme işlemini etkinlikle Compensate başlatmak için, CompensationTokenCompensableActivity telafinin istendiği ücret 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 CompensableActivity herhangi bir TryCatch zaman kullanılabilir. Bu örnekte etkinlik, Compensate bir etkinliğin Catches bölümünde öğesinin eylemini CompensableActivitytersine TryCatch ç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 etkinliğin onaylanması, tarafından ConfirmationHandlerbelirtilen 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 CompensableActivity belirtinCompensationToken.
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 CompensableActivityöğesinin Body bölümüne yerleştirilebilir. , CompensableActivity başka CompensableActivitybir işleyicisine yerleştirilmeyebilir. CompensableActivity İptal edildiğinde, onaylandığında veya telafi edildiğinde, ebeveynin iptali, onayı veya telafisi tamamlanmadan önce, henüz onaylanmamış veya tazmin edilmeyen tüm alt telafi edilebilir etkinliklerin onaylanması veya telafi edilmesi gerekir. 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 telafiyi işleme mantığı açıkça üst CompensableActivityöğesinin işleyicisinde modellenirse, açıkça işlenmemiş tüm alt öğeleri örtük olarak onaylanır.