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.
Het Transaction object wordt gemaakt met behulp van de DependentClone methode. Het enige doel is om te garanderen dat de transactie niet kan worden voltooid terwijl sommige andere code-elementen (bijvoorbeeld een worker thread) nog steeds werk aan de transactie uitvoeren. Wanneer het werk binnen de gekloonde transactie is voltooid en klaar is om te worden doorgevoerd, kan deze de maker van de transactie op de hoogte stellen met behulp van de Complete methode. Zo kunt u de consistentie en juistheid van gegevens behouden.
De DependentTransaction klasse kan ook worden gebruikt om gelijktijdigheid tussen asynchrone taken te beheren. In dit scenario kan het ouderproces enige code blijven uitvoeren, terwijl de afhankelijke clone op zijn eigen taken werkt. Met andere woorden, de uitvoering van de bovenliggende ouder wordt niet geblokkeerd totdat de afhankelijke is voltooid.
Een afhankelijke kloon maken
Als u een afhankelijke transactie wilt maken, roept u de DependentClone methode aan en geeft u de DependentCloneOption opsomming door als een parameter. Deze parameter definieert het gedrag van de transactie als Commit wordt aangeroepen op de bovenliggende transactie voordat de afhankelijke kloon aangeeft dat deze gereed is om de transactie te voltooien (door de Complete methode aan te roepen). De volgende waarden zijn geldig voor deze parameter:
BlockCommitUntilComplete maakt een afhankelijke transactie die het commitproces van de bovenliggende transactie blokkeert totdat de bovenliggende transactie een time-out heeft bereikt, of totdat Complete is aangeroepen op alle afhankelijke transacties om hun voltooiing aan te geven. Dit is handig wanneer de client niet wil dat de bovenliggende transactie wordt doorgevoerd totdat de afhankelijke transacties zijn voltooid. Als de bovenliggende transactie het werk eerder voltooit dan de afhankelijke transactie en een commit uitvoert op de transactie, wordt het commitproces geblokkeerd in een toestand waarin extra werk kan worden uitgevoerd op de transactie en nieuwe aanmeldingen kunnen worden gedaan, totdat alle afhankelijke transacties Commit aanroepen. Zodra ze allemaal klaar zijn met hun werk en Complete aanroepen, begint het commitproces voor de transactie.
RollbackIfNotCompletemaakt daarentegen een afhankelijke transactie die automatisch wordt afgebroken als Commit de bovenliggende transactie wordt aangeroepen voordat Complete deze wordt aangeroepen. In dit geval blijft al het werk dat in de afhankelijke transactie wordt uitgevoerd intact gedurende de hele levensduur van de transactie, en krijgt niemand de kans om slechts een deel ervan te bevestigen.
De Complete methode moet slechts eenmaal worden aangeroepen wanneer uw toepassing het werk van de afhankelijke transactie voltooit. Anders wordt er een InvalidOperationException gegenereerd. Nadat deze aanroep is aangeroepen, moet u geen extra werk op de transactie uitvoeren of wordt er een uitzondering gegenereerd.
In het volgende codevoorbeeld ziet u hoe u een afhankelijke transactie maakt om twee gelijktijdige taken te beheren door een afhankelijke transactie te klonen en door te geven aan een werkrolthread.
public class WorkerThread
{
public void DoWork(DependentTransaction dependentTransaction)
{
Thread thread = new Thread(ThreadMethod);
thread.Start(dependentTransaction);
}
public void ThreadMethod(object transaction)
{
DependentTransaction dependentTransaction = transaction as DependentTransaction;
Debug.Assert(dependentTransaction != null);
try
{
using(TransactionScope ts = new TransactionScope(dependentTransaction))
{
/* Perform transactional work here */
ts.Complete();
}
}
finally
{
dependentTransaction.Complete();
dependentTransaction.Dispose();
}
}
//Client code
using(TransactionScope scope = new TransactionScope())
{
Transaction currentTransaction = Transaction.Current;
DependentTransaction dependentTransaction;
dependentTransaction = currentTransaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
WorkerThread workerThread = new WorkerThread();
workerThread.DoWork(dependentTransaction);
/* Do some transactional work here, then: */
scope.Complete();
}
De clientcode maakt een transactioneel bereik waarmee ook de omgevingstransactie wordt ingesteld. Je moet de omgevingstransactie niet doorgeven aan de werker thread. In plaats daarvan moet u de huidige (omgevings)transactie klonen door de DependentClone-methode voor de huidige transactie aan te roepen en het afhankelijk object aan de werkdraad door te geven.
De ThreadMethod methode wordt uitgevoerd op de nieuwe thread. De client start een nieuwe thread, waarbij de afhankelijke transactie als parameter ThreadMethod wordt doorgegeven.
Omdat de afhankelijke transactie wordt gemaakt met BlockCommitUntilComplete, bent u gegarandeerd dat de transactie niet kan worden doorgevoerd totdat al het transactionele werk dat op de tweede thread is uitgevoerd, is voltooid en Complete wordt aangeroepen op de afhankelijke transactie. Dit betekent dat als het bereik van de client eindigt (wanneer het probeert het transactieobject aan het einde van de using instructie te verwijderen) voordat de nieuwe thread de afhankelijke transactie aanroept Complete , de clientcode blokkeert totdat Complete het afhankelijke object wordt aangeroepen. Vervolgens kan de transactie het doorvoeren of afbreken voltooien.
Problemen met gelijktijdigheid
Er zijn enkele extra gelijktijdigheidsproblemen waarmee u rekening moet houden bij het gebruik van de DependentTransaction klasse:
Als de worker thread de transactie terugdraait, maar de ouder deze probeert door te voeren, wordt er een TransactionAbortedException gegooid.
U moet een nieuwe afhankelijke kloon maken voor elke werkrolthread in de transactie. Geef dezelfde dependente kloon niet door aan meerdere threads, omdat slechts één van deze threads Complete erop kan aanroepen.
Als de werkthread een nieuwe werkthread voortbrengt, moet u een afhankelijke kloon maken van de oorspronkelijke afhankelijke kloon en deze doorgeven aan de nieuwe thread.