Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
AsyncCodeActivity biedt auteurs van activiteiten een basisklasse die afgeleide activiteiten in staat stelt asynchrone uitvoeringslogica te implementeren. Dit is handig voor aangepaste activiteiten die asynchroon werk moeten uitvoeren zonder de thread van de werkstroomplanner vast te houden en activiteiten te blokkeren die parallel kunnen worden uitgevoerd. In dit onderwerp vindt u een overzicht van het maken van aangepaste asynchrone activiteiten met behulp van AsyncCodeActivity.
AsyncCodeActivity gebruiken
System.Activities biedt auteurs van aangepaste activiteiten verschillende basisklassen voor verschillende vereisten voor het ontwerpen van activiteiten. Elk element draagt een bepaalde semantiek en geeft een werkstroomauteur (en de activiteitsruntime) een bijbehorend contract. Een activiteit op basis van AsyncCodeActivity is een activiteit die asynchroon werk uitvoert ten opzichte van de scheduler-draad en waarvan de uitvoeringslogica wordt uitgedrukt in beheerde code. Als gevolg van het asynchroon worden, kan een AsyncCodeActivity een inactief moment veroorzaken tijdens de uitvoering. Vanwege de onvoorspelbare aard van asynchroon werk wordt er altijd een niet persistent blok gemaakt voor de duur van de uitvoering van de activiteit. Hiermee voorkomt u dat de werkstroomruntime het werkstroomexemplaar opslaat midden in het asynchrone werk, en ook dat het werkstroomexemplaar wordt verwijderd terwijl de asynchrone code wordt uitgevoerd.
AsyncCodeActivity-methoden
Activiteiten die zijn afgeleid van AsyncCodeActivity , kunnen asynchrone uitvoeringslogica maken door de BeginExecute en EndExecute methoden met aangepaste code te overschrijven. Wanneer ze door de runtime worden aangeroepen, krijgen deze methoden een AsyncCodeActivityContext mee.
AsyncCodeActivityContext staat de auteur van de activiteit toe om een gedeelde toestand te BeginExecute/ EndExecute bieden in de context van de eigenschap UserState. In het volgende voorbeeld genereert een GenerateRandom activiteit asynchroon een willekeurig getal.
public sealed class GenerateRandom : AsyncCodeActivity<int>
{
static Random r = new Random();
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
// Create a delegate that references the method that implements
// the asynchronous work. Assign the delegate to the UserState,
// invoke the delegate, and return the resulting IAsyncResult.
Func<int> GetRandomDelegate = new Func<int>(GetRandom);
context.UserState = GetRandomDelegate;
return GetRandomDelegate.BeginInvoke(callback, state);
}
protected override int EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
// Get the delegate from the UserState and call EndInvoke
Func<int> GetRandomDelegate = (Func<int>)context.UserState;
return (int)GetRandomDelegate.EndInvoke(result);
}
int GetRandom()
{
// This activity simulates taking a few moments
// to generate the random number. This code runs
// asynchronously with respect to the workflow thread.
Thread.Sleep(5000);
return r.Next(1, 101);
}
}
De vorige voorbeeldactiviteit is afgeleid van AsyncCodeActivity<TResult> en heeft een verheven OutArgument<int> genaamd Result. De waarde die door de GetRandom methode wordt geretourneerd, wordt geëxtraheerd en geretourneerd door de EndExecute overschrijving en deze waarde wordt ingesteld als de Result waarde. Asynchrone activiteiten die geen resultaat retourneren, moeten worden afgeleid van AsyncCodeActivity. In het volgende voorbeeld wordt een DisplayRandom activiteit gedefinieerd die is afgeleid van AsyncCodeActivity. Deze activiteit is vergelijkbaar met de GetRandom activiteit, maar in plaats van een resultaat te retourneren, wordt er een bericht naar de console weergegeven.
public sealed class DisplayRandom : AsyncCodeActivity
{
static Random r = new Random();
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
// Create a delegate that references the method that implements
// the asynchronous work. Assign the delegate to the UserState,
// invoke the delegate, and return the resulting IAsyncResult.
Action GetRandomDelegate = new Action(GetRandom);
context.UserState = GetRandomDelegate;
return GetRandomDelegate.BeginInvoke(callback, state);
}
protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
// Get the delegate from the UserState and call EndInvoke
Action GetRandomDelegate = (Action)context.UserState;
GetRandomDelegate.EndInvoke(result);
}
void GetRandom()
{
// This activity simulates taking a few moments
// to generate the random number. This code runs
// asynchronously with respect to the workflow thread.
Thread.Sleep(5000);
Console.WriteLine($"Random Number: {r.Next(1, 101)}");
}
}
Omdat er geen retourwaarde is, gebruikt DisplayRandom een Action in plaats van een Func<T,TResult> om zijn gedelegeerde aan te roepen, en retourneert de gedelegeerde geen waarde.
AsyncCodeActivity biedt ook een Cancel overschrijving. Hoewel BeginExecute en EndExecute vereiste overschrijvingen zijn, is Cancel optioneel en kan worden overschreven, zodat de activiteit de openstaande asynchrone status kan opschonen wanneer deze wordt geannuleerd of afgebroken. Als opschonen mogelijk is en AsyncCodeActivity.ExecutingActivityInstance.IsCancellationRequested is true, moet de activiteit MarkCanceled aanroepen. Eventuele uitzonderingen die van deze methode worden gegooid, zijn fataal voor de workflow-instanties.
protected override void Cancel(AsyncCodeActivityContext context)
{
// Implement any cleanup as a result of the asynchronous work
// being canceled, and then call MarkCanceled.
if (context.IsCancellationRequested)
{
context.MarkCanceled();
}
}
Asynchrone methoden aanroepen in een klasse
Veel van de klassen in .NET Framework bieden asynchrone functionaliteit en deze functionaliteit kan asynchroon worden aangeroepen met behulp van een activiteit op basis van een AsyncCodeActivity activiteit. In het volgende voorbeeld wordt een activiteit gemaakt die asynchroon een bestand maakt met behulp van de FileStream klasse.
public sealed class FileWriter : AsyncCodeActivity
{
public FileWriter()
: base()
{
}
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
string tempFileName = Path.GetTempFileName();
Console.WriteLine("Writing to file: " + tempFileName);
FileStream file = File.Open(tempFileName, FileMode.Create);
context.UserState = file;
byte[] bytes = UnicodeEncoding.Unicode.GetBytes("123456789");
return file.BeginWrite(bytes, 0, bytes.Length, callback, state);
}
protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
FileStream file = (FileStream)context.UserState;
try
{
file.EndWrite(result);
file.Flush();
}
finally
{
file.Close();
}
}
}
Deelstatus tussen de Methoden BeginExecute en EndExecute
In het vorige voorbeeld werd toegang verkregen tot het FileStream object dat was gemaakt in BeginExecute in de EndExecute. Dit is mogelijk omdat de file variabele is doorgegeven in de AsyncCodeActivityContext.UserState eigenschap in BeginExecute. Dit is de juiste methode voor het delen van de status tussen BeginExecute en EndExecute. Het is onjuist om een lidvariabele te gebruiken in de afgeleide klasse (FileWriter in dit geval) om de status te delen tussen BeginExecute en EndExecute omdat naar het activiteitsobject kan worden verwezen door meerdere activiteitsexemplaren. Als u probeert een lidvariabele te gebruiken om de status te delen, kan dit resulteren in waardes van de ene ActivityInstance die de waardes van een andere ActivityInstance overschrijven of consumeren.
Argumentwaarden openen
De omgeving van een AsyncCodeActivity bestand bestaat uit de argumenten die zijn gedefinieerd voor de activiteit. Deze argumenten zijn toegankelijk vanuit de BeginExecute/EndExecute overschrijvingen met behulp van de AsyncCodeActivityContext parameter. De argumenten kunnen niet worden geopend in de gemachtigde, maar de argumentwaarden of andere gewenste gegevens kunnen worden doorgegeven aan de gemachtigde met behulp van de parameters. In het volgende voorbeeld wordt een willekeurige activiteit voor het genereren van getallen gedefinieerd waarmee de inclusieve bovengrens van het Max argument wordt opgehaald. De waarde van het argument wordt doorgegeven aan de asynchrone code wanneer de gemachtigde wordt aangeroepen.
public sealed class GenerateRandomMax : AsyncCodeActivity<int>
{
public InArgument<int> Max { get; set; }
static Random r = new Random();
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
// Create a delegate that references the method that implements
// the asynchronous work. Assign the delegate to the UserState,
// invoke the delegate, and return the resulting IAsyncResult.
Func<int, int> GetRandomDelegate = new Func<int, int>(GetRandom);
context.UserState = GetRandomDelegate;
return GetRandomDelegate.BeginInvoke(Max.Get(context), callback, state);
}
protected override int EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
// Get the delegate from the UserState and call EndInvoke
Func<int, int> GetRandomDelegate = (Func<int, int>)context.UserState;
return (int)GetRandomDelegate.EndInvoke(result);
}
int GetRandom(int max)
{
// This activity simulates taking a few moments
// to generate the random number. This code runs
// asynchronously with respect to the workflow thread.
Thread.Sleep(5000);
return r.Next(1, max + 1);
}
}
Acties of onderliggende activiteiten plannen met behulp van AsyncCodeActivity
AsyncCodeActivity afgeleide aangepaste activiteiten bieden een methode voor het asynchroon uitvoeren van taken ten opzichte van de workflow-thread, maar bieden niet de mogelijkheid om kindactiviteiten of acties te plannen. Asynchroon gedrag kan echter worden opgenomen door het plannen van subactiviteiten door middel van compositie. Een asynchrone activiteit kan worden gemaakt en vervolgens gecombineerd met een Activity of NativeActivity afgeleide activiteit om asynchroon gedrag en het inroosteren van onderliggende activiteiten of acties te bieden. Een activiteit kan bijvoorbeeld worden gemaakt die is afgeleid van Activityen die als implementatie een Sequence activiteit bevat die de asynchrone activiteit bevat, evenals de andere activiteiten die de logica van de activiteit implementeren. Zie voor meer voorbeelden van het samenstellen van activiteiten met Activity en NativeActivity, Hoe: Een Activiteit Maken en Opties voor Activiteitensamenstelling.