Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
L’objet Transaction est créé à l’aide de la DependentClone méthode. Son seul objectif est de garantir que la transaction ne peut pas être validée alors que d’autres éléments de code (par exemple, un thread de travail) effectuent toujours un travail sur la transaction. Une fois le travail sur la transaction clonée effectué et prêt pour validation, il peut informer le créateur de la transaction à l'aide de la méthode Complete. Ainsi, vous pouvez conserver la cohérence et la correction des données.
La DependentTransaction classe peut également être utilisée pour gérer la concurrence entre les tâches asynchrones. Dans ce scénario, le parent peut continuer à exécuter n’importe quel code pendant que le clone dépendant fonctionne sur ses propres tâches. En d'autres termes, l'exécution de la transaction parent n'est pas bloquée lorsque le clone dépendant travaille.
Création d’un clone dépendant
Pour créer une transaction dépendante, appelez la DependentClone méthode et transmettez l’énumération DependentCloneOption en tant que paramètre. Ce paramètre définit le comportement de la transaction si Commit est appelée sur la transaction parente avant que le clone dépendant n'indique qu'il est prêt pour la validation de la transaction (en appelant la méthode Complete). Les valeurs suivantes sont valides pour ce paramètre :
BlockCommitUntilComplete crée une transaction dépendante qui bloque le processus de validation de la transaction parente jusqu’à ce que la transaction parente atteigne le délai d’expiration, ou jusqu’à ce que Complete soit appelé sur toutes les transactions dépendantes indiquant leur achèvement. Cela est utile lorsque le client ne souhaite pas que la transaction parente soit validée tant que les transactions dépendantes n’ont pas été effectuées. Si le parent termine son travail avant la transaction dépendante et appelle Commit sur la transaction, le processus de validation est bloqué dans un état où des tâches supplémentaires peuvent être effectuées sur la transaction et de nouvelles inscriptions peuvent être créées, jusqu’à ce que tous les dépendants appellent Complete. Dès que tous ces derniers ont terminé leur travail et appellent Complete, le processus de validation de la transaction commence.
RollbackIfNotComplete, d’autre part, crée une transaction dépendante qui abandonne automatiquement si Commit elle est appelée sur la transaction parente avant Complete d’être appelée. Dans ce cas, tout le travail effectué dans la transaction dépendante reste intact pendant la durée de vie d'une transaction, et personne n’a la possibilité de valider uniquement une partie de celle-ci.
La méthode Complete ne doit être appelée qu'une fois lorsque votre application termine son travail sur la transaction dépendante ; sinon, une InvalidOperationException est levée. Après cet appel, ne tentez pas d'effectuer un travail supplémentaire sur la transaction sous peine de lever une exception.
L’exemple de code suivant montre comment créer une transaction dépendante pour gérer deux tâches simultanées en clonant une transaction dépendante et en la transmettant à un thread de travail.
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();
}
Le code client crée une étendue transactionnelle qui définit également la transaction ambiante. Ne passez pas la transaction ambiante au thread de travail. À la place, clonez la transaction (ambiante) en cours en appelant la méthode DependentClone sur la transaction en cours et passez le clone dépendant au thread de travail.
La ThreadMethod méthode s’exécute sur le nouveau thread. Le client démarre un nouveau fil, en passant la transaction dépendante comme paramètre ThreadMethod.
Étant donné que la transaction dépendante est créée avec BlockCommitUntilComplete, vous êtes garanti que la transaction ne peut pas être validée tant que toutes les tâches transactionnelles effectuées sur le deuxième thread sont terminées et Complete appelées sur la transaction dépendante. Cela signifie que si l’étendue du client se termine (lorsque celui-ci tente de supprimer l'objet de transaction à la fin de l'instruction using) avant que le nouveau thread n'appelle Complete sur la transaction dépendante, le code client se bloque jusqu'à ce que Complete soit appelé sur la transaction dépendante. La transaction peut ensuite terminer la validation ou l'abandon.
Problèmes de concurrence
Il existe quelques problèmes d’accès concurrentiel supplémentaires que vous devez connaître lors de l’utilisation de la DependentTransaction classe :
Si le thread de travail restaure la transaction mais que le parent tente sa validation, une TransactionAbortedException est levée.
Vous devez créer un clone dépendant pour chaque thread de travail de la transaction. Ne transmettez pas le même clone dépendant à plusieurs threads, car un seul d’entre eux peut l’appeler Complete .
Si le thread de travail génère un nouveau thread de travail, veillez à créer un clone dépendant à partir du clone dépendant et à le transmettre au nouveau thread.