Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O Transaction objeto é criado usando o DependentClone método. Sua única finalidade é garantir que a transação não possa ser confirmada enquanto algumas outras partes do código (por exemplo, um thread de trabalho) ainda estiverem executando trabalho na transação. Quando o trabalho feito dentro da transação clonada estiver concluído e pronto para ser confirmado, ele poderá notificar o criador da transação usando o Complete método. Assim, você pode preservar a consistência e a correção dos dados.
A DependentTransaction classe também pode ser usada para gerenciar a simultaneidade entre tarefas assíncronas. Nesse cenário, o pai pode continuar a executar qualquer código enquanto o clone dependente funciona em suas próprias tarefas. Em outras palavras, a execução do pai não é bloqueada até que o dependente é concluída.
Criando um Clone dependente
Para criar uma transação dependente, chame o DependentClone método e passe a DependentCloneOption enumeração como um parâmetro. Esse parâmetro define o comportamento da transação se Commit
é chamado na transação pai antes que o clone dependente indica que ele está pronto para a transação seja confirmada (chamando o Complete método). Os seguintes valores são válidos para este parâmetro:
BlockCommitUntilComplete cria uma transação dependente que bloqueia o processo de confirmação da transação pai até a transação pai atingir o tempo limite ou até que Complete seja chamado em todos os dependentes indicando a conclusão. Isso é útil quando o cliente não deseja que a transação principal seja concluída até que as transações subordinadas tenham sido concluídas. Se o pai concluir seu trabalho antes que a transação dependente e chamadas Commit na transação, o processo de confirmação será bloqueado em um estado onde trabalho adicional pode ser feito na transação e novas inscrições podem ser criadas, até que todos os da chamada dependentes Complete. Assim que todos eles terminarem seu trabalho e fizerem a chamada Complete, o processo de confirmação da transação começa.
RollbackIfNotComplete, por outro lado, cria uma transação dependente que anula automaticamente se Commit for chamado na transação pai antes que Complete seja chamado. Nesse caso, todo o trabalho feito na transação dependente permanece intacto durante toda a duração da transação, e ninguém tem a oportunidade de comprometer apenas uma parte dela.
O Complete método deve ser chamado apenas uma vez quando seu aplicativo termina seu trabalho na transação dependente; Caso contrário, um InvalidOperationException é lançada. Depois que essa chamada é invocada, você não deve tentar qualquer trabalho adicional na transação ou uma exceção é lançada.
O exemplo de código a seguir mostra como criar uma transação dependente para gerenciar duas tarefas simultâneas clonando uma transação dependente e passando-a para um thread de trabalho.
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();
}
O código do cliente cria um escopo transacional que também define a transação ambiente. Você não deve passar a transação de ambiente para o thread de trabalho. Em vez disso, você deve clonar a transação (ambiente) atual chamando o DependentClone método na transação atual e passe o dependente para o thread de trabalho.
O ThreadMethod
método é executado no novo thread. O cliente inicia um novo thread, passando a transação dependente como o ThreadMethod
parâmetro.
Como a transação dependente é criada com BlockCommitUntilComplete, você tem a garantia de que a transação não pode ser confirmada até que todo o trabalho transacional feito no segundo thread seja concluído e Complete seja chamado na transação dependente. Isso significa que, se o escopo do cliente terminar (quando ele tentar descartar o objeto de transação no final da instrução using
) antes do novo encadeamento chamar Complete na transação dependente, o código do cliente será bloqueado até que Complete seja chamado no dependente. Em seguida, a transação pode concluir a confirmação ou anulação.
Problemas de concorrência
Há alguns problemas de simultaneidade adicionais que você precisa estar ciente ao usar a DependentTransaction classe:
Se o thread de trabalho reverte a transação, mas o pai tenta confirmar, um TransactionAbortedException é lançada.
Você deve criar um novo clone dependente para cada thread de trabalho na transação. Não passam o mesmo clone dependente em vários threads, porque apenas um deles pode chamar Complete nele.
Se o thread de trabalho gera um novo thread de trabalho, certifique-se de criar um clone dependente do clone dependente e passá-lo para o novo thread.