2012-03-21 18 views
5

Ho una classe che salva le informazioni di registrazione nel database (in un metodo NServiceBus Handle).Eseguire in modo condizionale i metodi di una classe su un thread separato

La maggior parte delle volte che è possibile eseguire la registrazione su un thread separato (e una transazione) dal processo principale. Ma tutto deve essere fatto sullo stesso thread di background (il che significa che devono essere eseguiti in ordine, ma non sincronizzati con il processo principale).

Tuttavia, una volta avviata la codifica esterna per i dati effettivi da NServiceBus, è necessario che sia sullo stesso thread.

Ecco qualche esempio di codice:

public class MyExample 
{ 

    public void LogSomeStuff(Stuff stuff) 
    { 
     using (MoveOutsideTransaction()) 
     { 
     // Do Method Stuff here 
     dataAccess.SaveChanges(); 
     } 
    } 


    public void LogSomeOtherStuff(Stuff stuff) 
    { 
     using (MoveOutsideTransaction()) 
     { 
     // Do Other Method Stuff here 
     dataAccess.SaveChanges(); 
     } 
    } 

    private IDisposable MoveOutsideTransaction() 
    { 
     if (loggingOutsideTransaction) 
      return new TransactionScope(TransactionScopeOption.Suppress); 

     return null; 
    } 
} 

Mi chiedo se c'è un modo di usare la mia transazione condizionale per anche condizionalmente spostare la corsa per un thread diverso. (Ma solo quando si sopprime la transazione.)

risposta

2

Mi chiedo se c'è un modo di usare la mia transazione condizionale per anche condizionalmente spostare la corsa per un thread diverso.

Non è possibile spostare l'esecuzione di un metodo su un thread diverso. I thread non funzionano in questo modo in generale. Tuttavia, ciò che si può fare è impostare un thread dedicato che possa partecipare a un'operazione di marshalling che, più o meno, simula il trasferimento dell'esecuzione su un altro thread. È importante portare a casa il punto che questo thread dedicato deve essere codificato in modo specifico per accettare questa operazione di marshalling.

Ecco come funziona.

public class DedicatedThread 
{ 
    private BlockingCollection<Action> actions = new BlockingCollection<Action>(); 

    public DedicatedThread() 
    { 
    var thread = new Thread(
    () => 
     { 
     while (true) 
     { 
      Action action = actions.Take(); 
      action(); 
     } 
     }); 
    } 

    public void SubmitAction(Action action) 
    { 
    actions.Add(action); 
    } 
} 

E si potrebbe usare in questo modo.

if (loggingOutsideTransaction) 
{ 
    // Execute asynchronously on a dedicated thread. 
    dedicatedThread.SubmitAction(yourActionDelegate); 
} 
else 
{ 
    // Execute synchronously. 
    yourActionDelegate(); 
} 
+0

Questo sembra fantastico, ma molti dei miei metodi hanno diversi parametri. La maggior parte sono 'string's e' int's ma ho bisogno di passarli. C'è un modo per farlo con questa configurazione? (Questo sembra solo chiamare il metodo, ma non consente i parametri con ciascuna chiamata.) – Vaccano

+2

@Vaccano: puoi usare l'azione invece. Oppure quando costruisci il delegato 'Action' tramite espressione lambda puoi fare chiusure su variabili. –

Problemi correlati