Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Aktiviteter kan avbrytas i ett arbetsflöde, till exempel genom att en Parallel-aktivitet avbryter ofullständiga grenar när dess CompletionCondition utvärderas till true, eller från utsidan av arbetsflödet, om värden anropar Cancel. För att tillhandahålla hantering av avbokningar kan arbetsflödesförfattare använda CancellationScope-aktiviteten, CompensableActivity-aktiviteten eller skapa anpassade aktiviteter som tillhandahåller avbokningslogik. Det här avsnittet innehåller en översikt över annullering i arbetsflöden.
Annullering, kompensation och transaktioner
Transaktioner ger ditt program möjlighet att avbryta (återställa) alla ändringar som körs i transaktionen om några fel inträffar under någon del av transaktionsprocessen. Allt arbete som kan behöva avbrytas eller ångras är dock inte lämpligt för transaktioner, till exempel långvarigt arbete eller arbete som inte omfattar transaktionsresurser. Kompensation ger en modell för att ångra tidigare slutfört icke-transaktionellt arbete om det uppstår ett efterföljande fel i arbetsflödet. Annullering tillhandahåller en modell för arbetsflödes- och aktivitetsförfattare som hanterar icke-transaktionellt arbete som inte har slutförts. Om en aktivitet inte har slutfört körningen och den avbryts anropas dess annulleringslogik om den är tillgänglig.
Kommentar
Mer information om transaktioner och kompensation finns i Transaktioner och kompensation.
Använda CancellationScope
Aktiviteten CancellationScope har två sektioner som kan innehålla underliggande aktiviteter: Body och CancellationHandler. Det Body är där aktiviteterna som utgör aktivitetens logik placeras och CancellationHandler det är där aktiviteterna som tillhandahåller annulleringslogik för aktiviteten placeras. En aktivitet kan bara avbrytas om den inte har slutförts. När det gäller aktiviteten CancellationScope avser slutförandet slutförandet av aktiviteterna i Body. Om en annulleringsbegäran har schemalagts och aktiviteterna i Body inte har slutförts, kommer CancellationScope att markeras som Canceled och aktiviteterna CancellationHandler kommer att köras.
Avbryta ett arbetsflöde från en värd
En värd kan avbryta ett arbetsflöde genom att anropa metoden för den CancelWorkflowApplication instans som är värd för arbetsflödet. I följande exempel skapas ett arbetsflöde som har en CancellationScope. Arbetsflödet aktiveras och sedan anropar värden Cancel. Huvudkörningen av arbetsflödet stoppas, CancellationHandler av CancellationScope anropas, och sedan slutförs arbetsflödet med statusen Canceled.
Activity wf = new CancellationScope
{
Body = new Sequence
{
Activities =
{
new WriteLine
{
Text = "Starting the workflow."
},
new Delay
{
Duration = TimeSpan.FromSeconds(5)
},
new WriteLine
{
Text = "Ending the workflow."
}
}
},
CancellationHandler = new WriteLine
{
Text = "CancellationHandler invoked."
}
};
// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);
// 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.");
}
};
// Run the workflow.
wfApp.Run();
Thread.Sleep(TimeSpan.FromSeconds(1));
wfApp.Cancel();
När det här arbetsflödet anropas visas följande utdata för konsolen.
Starta arbetsflödet.
CancellationHandler anropas.Arbetsflöde b30ebb30-df46-4d90-a211-e31c38d8db3c Avbröts.
Kommentar
När en CancellationScope aktivitet avbryts och anropas CancellationHandler är det arbetsflödesförfattarens ansvar att fastställa förloppet för den avbrutna aktiviteten som gjordes innan den avbröts för att tillhandahålla lämplig annulleringslogik. CancellationHandler Innehåller ingen information om förloppet för den avbrutna aktiviteten.
Ett arbetsflöde kan också avbrytas från värddatorn om ett ohanterat undantag propagerar förbi arbetsflödets rot och OnUnhandledException hanteraren returnerar Cancel. I det här exemplet startar arbetsflödet och genererar sedan en ApplicationException. Det här undantaget hanteras inte av arbetsflödet och därför OnUnhandledException anropas hanteraren. Hanteraren instruerar körningen att avbryta arbetsflödet, och CancellationHandler av den för närvarande körda CancellationScope-aktiviteten anropas.
Activity wf = new CancellationScope
{
Body = new Sequence
{
Activities =
{
new WriteLine
{
Text = "Starting the workflow."
},
new Throw
{
Exception = new InArgument<Exception>((env) =>
new ApplicationException("An ApplicationException was thrown."))
},
new WriteLine
{
Text = "Ending the workflow."
}
}
},
CancellationHandler = new WriteLine
{
Text = "CancellationHandler invoked."
}
};
// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);
// Subscribe to any desired workflow lifecycle events.
wfApp.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
// Display the unhandled exception.
Console.WriteLine($"OnUnhandledException in Workflow {e.InstanceId}\n{e.UnhandledException.Message}");
// Instruct the runtime to cancel the workflow.
return UnhandledExceptionAction.Cancel;
};
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.");
}
};
// Run the workflow.
wfApp.Run();
När det här arbetsflödet anropas visas följande utdata för konsolen.
Starta arbetsflödet.
OnUnhandledException i arbetsflödet 6bb2d5d6-f49a-4c6d-a988-478afb86dbe9En ApplicationException kastades.CancellationHandler anropas.Arbetsflödet 6bb2d5d6-f49a-4c6d-a988-478afb86dbe9 avbröts.
Avbryta en aktivitet inifrån ett arbetsflöde
En aktivitet kan också avbrytas av dess förälder. Om en Parallel-aktivitet till exempel har flera grenar som körs och dess CompletionCondition utvärderas till true, kommer dess ofullständiga grenar att avbrytas. I det här exemplet skapas en Parallel aktivitet som har två grenar. Dess CompletionCondition är inställd på true, så att Parallel slutförs så snart någon av dess grenar är avslutad. I det här exemplet slutförs gren 2, så gren 1 avbryts.
Activity wf = new Parallel
{
CompletionCondition = true,
Branches =
{
new CancellationScope
{
Body = new Sequence
{
Activities =
{
new WriteLine
{
Text = "Branch 1 starting."
},
new Delay
{
Duration = TimeSpan.FromSeconds(2)
},
new WriteLine
{
Text = "Branch 1 complete."
}
}
},
CancellationHandler = new WriteLine
{
Text = "Branch 1 canceled."
}
},
new WriteLine
{
Text = "Branch 2 complete."
}
}
};
// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);
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.");
}
};
// Run the workflow.
wfApp.Run();
När det här arbetsflödet anropas visas följande utdata för konsolen.
Gren 1 börjar.
Gren 2 är klar.Gren 1 avbröts.Arbetsflödet e0685e24-18ef-4a47-acf3-5c638732f3be Slutfört. Aktiviteter avbryts också om ett undantag bubblar upp efter aktivitetens rot men hanteras på en högre nivå i arbetsflödet. I det här exemplet består huvudlogik för arbetsflödet av en Sequence aktivitet.
Sequence anges som Body för en CancellationScope aktivitet som innefattas av en TryCatch aktivitet. Ett undantag genereras från brödtexten i Sequence, hanteras av den överordnade TryCatch aktiviteten och Sequence avbryts.
Activity wf = new TryCatch
{
Try = new CancellationScope
{
Body = new Sequence
{
Activities =
{
new WriteLine
{
Text = "Sequence starting."
},
new Throw
{
Exception = new InArgument<Exception>((env) =>
new ApplicationException("An ApplicationException was thrown."))
},
new WriteLine
{
Text = "Sequence complete."
}
}
},
CancellationHandler = new WriteLine
{
Text = "Sequence canceled."
}
},
Catches =
{
new Catch<ApplicationException>
{
Action = new ActivityAction<ApplicationException>
{
Handler = new WriteLine
{
Text = "Exception caught."
}
}
}
}
};
// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);
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.");
}
};
// Run the workflow.
wfApp.Run();
När det här arbetsflödet anropas visas följande utdata för konsolen.
Sekvensen startar.
Sekvensen avbröts.Undantag fångat.Arbetsflöde e3c18939-121e-4c43-af1c-ba1ce977ce55 slutfört.
Utlöser undantag från en CancellationHandler
Alla undantag som genereras från CancellationHandler av en CancellationScope är dödliga för arbetsflödet. Om det finns en möjlighet att undantag kan uppstå från en CancellationHandler, ska du använda en TryCatch i CancellationHandler för att fånga och hantera dessa undantag.
Annullering med CompensableActivity
Liksom CancellationScope-aktiviteten har CompensableActivity en CancellationHandler. Om en CompensableActivity avbryts, anropas alla aktiviteter i dess CancellationHandler. Detta kan vara användbart för att ångra delvis slutfört kompenserbart arbete. Information om hur du använder CompensableActivity för kompensation och annullering finns i Kompensation.
Annullering med anpassade aktiviteter
Författare av anpassad aktivitet kan implementera annulleringslogik i sina anpassade aktiviteter på flera olika sätt. Anpassade aktiviteter som härleds från Activity kan implementera annulleringslogik genom att placera en CancellationScope eller annan anpassad aktivitet som innehåller annulleringslogik i aktivitetens brödtext. AsyncCodeActivity och NativeActivity härledda aktiviteter kan åsidosätta respektive Cancel metod och tillhandahålla annulleringslogik där. CodeActivity härledda aktiviteter tillhandahåller ingen möjlighet för annullering eftersom allt deras arbete utförs vid ett enda tillfälle när körningen anropar Execute-metoden. Om körningsmetoden ännu inte har anropats och en CodeActivity-baserad aktivitet avbryts, stängs aktiviteten med statusen Canceled och metoden Execute anropas inte.
Annullering med NativeActivity
NativeActivity härledda aktiviteter kan åsidosätta Cancel metoden för att tillhandahålla anpassad annulleringslogik. Om den här metoden inte åsidosätts tillämpas standardlogik för arbetsflödesavbokning. Standardavbokning är den process som inträffar för en NativeActivity som inte åsidosätter Cancel metoden eller vars Cancel metod anropar basmetoden NativeActivityCancel . När en aktivitet avbokas flaggar programmet aktiviteten för avbokning och hanterar automatiskt viss uppstädning. Om aktiviteten bara har utestående bokmärken tas bokmärkena bort och aktiviteten markeras som Canceled. Eventuella utestående underordnade aktiviteter för den avbrutna aktiviteten kommer i sin tur att avbrytas. Alla försök att schemalägga ytterligare barnaktiviteter kommer att ignoreras och aktiviteten markeras som Canceled. Om någon pågående underordnad aktivitet slutförs i tillståndet Canceled eller Faulted, då markeras aktiviteten som Canceled. Observera att en begäran om annullering kan ignoreras. Om en aktivitet inte har några utestående bokmärken eller kör några underordnade aktiviteter, och inte schemalägger några ytterligare arbetsuppgifter efter att ha markerats för annullering, kommer den att slutföras framgångsrikt. Den här standardavbokningen räcker för många scenarier, men om ytterligare avbokningslogik behövs kan de inbyggda avbokningsaktiviteterna eller anpassade aktiviteterna användas.
I följande exempel definieras åsidosättningen av en anpassad Cancel-baserad NativeActivity-aktivitet ParallelForEach. När en aktivitet avbryts hanterar den här åsidosättningen logiken för avbokning av aktiviteten. Det här exemplet är en del av exemplet Non-Generic ParallelForEach .
protected override void Cancel(NativeActivityContext context)
{
// If we do not have a completion condition then we can just
// use default logic.
if (this.CompletionCondition == null)
{
base.Cancel(context);
}
else
{
context.CancelChildren();
}
}
NativeActivity härledda aktiviteter kan inspektera IsCancellationRequested-egenskapen för att avgöra om en begäran om annullering har gjorts, och sedan markera sig själva som avbruten genom att anropa MarkCanceled-metoden. Anropet MarkCanceled slutför inte aktiviteten omedelbart. Som vanligt slutför körningen aktiviteten när den inte har något mer enastående arbete, men om MarkCanceled anropas kommer det slutliga tillståndet att vara Canceled i stället för Closed.
Annullering med AsyncCodeActivity
AsyncCodeActivity-baserade aktiviteter kan också tillhandahålla anpassad annulleringslogik genom att åsidosätta Cancel-metoden. Om den här metoden inte åsidosätts utförs ingen avbokningshantering om aktiviteten avbryts. I följande exempel definieras åsidosättningen Cancel av en AsyncCodeActivity baserad anpassad ExecutePowerShell aktivitet. När aktiviteten avbryts utför den det önskade avbokningsbeteendet.
// Called by the runtime to cancel the execution of this asynchronous activity.
protected override void Cancel(AsyncCodeActivityContext context)
{
Pipeline pipeline = context.UserState as Pipeline;
if (pipeline != null)
{
pipeline.Stop();
DisposePipeline(pipeline);
}
base.Cancel(context);
}
AsyncCodeActivity härledda aktiviteter kan inspektera IsCancellationRequested-egenskapen för att avgöra om en begäran om annullering har gjorts, och sedan markera sig själva som avbruten genom att anropa MarkCanceled-metoden.