2013-01-02 17 views
6

Possiedo un sito Web che utilizza MSMQ su un server remoto per accodare le e-mail in sospeso. Sono in grado di scrivere il messaggio in coda, quindi chiamare la disposizione in coda. La coda riceve ancora il messaggio, ma a volte il GC arriva e tenta di ripulire e provoca l'arresto anomalo di IIS. Questo è quello che vedo nel registro eventi:MSMQ CreateCursor NullReferenceException

Eccezione: System.NullReferenceException

messaggio: riferimento oggetto non impostato su un'istanza di un oggetto.

StackTrace: at System.Messaging.Cursor.Finalize()

Questo codice sta funzionando benissimo per anni, ma appena iniziato a recitare di recente. Ho riavviato tutti i server per risolverlo, ma questo non aiuta.

Modifica 1

Qui è il codice che sta inviando i messaggi. QueueFactory è solo un singleton che ha un blocco attorno alla creazione di un MessageQueue.

using (System.Messaging.MessageQueue queue 
    = QueueFactory.Instance.BuildQueue(this.Path)) 
{ 
    System.Messaging.Message message = new System.Messaging.Message 
    { 
     Body = body, 
     Formatter = new BinaryMessageFormatter(), 
     TimeToBeReceived = this.ExpirationMinutes 
    }; 

    queue.Send(message, label); 
} 

C'è un try-catch intorno a questo codice, e so che non lo rende nel blocco catch. Sto iniziando a pensare che questo è stato causato quando l'intera applicazione è stata aggiornata da .NET 3.5 a .NET 4.0. Tuttavia ha iniziato a verificarsi sporadicamente, ma ora accade ogni volta che scrivo un messaggio in coda.

Edit 2

Qui è il codice per BuildQueue

lock (lockHandler) 
{ 
    return new System.Messaging.MessageQueue(queuePath); 
} 
+0

potrebbe desiderare di aggiungere ulteriori informazioni come ... completa analisi dello stack, codice sorgente che fa la coda e dispone la coda. Sembra che se si dispone di garbage collection non è necessario disporre l'obiezione da soli. –

+0

Questa è l'intera traccia dello stack, e sto semplicemente chiamando Send su un oggetto MessageQueue, che è stato costruito in un blocco using. Penso che sia piuttosto normale che gli oggetti disposti vengano visitati dal GC. – goalie7960

+0

quindi la tua eccezione si verifica sul server che sta accodando i messaggi o sul server remoto che li sta leggendo? Da MSDN "Un cursore viene utilizzato per mantenere una posizione specifica in un MessageQueue durante la lettura dei messaggi della coda." http://msdn.microsoft.com/en-us/library/system.messaging.cursor.aspx –

risposta

0

Provare a usare una transazione:

using (System.Messaging.MessageQueue queue 
    = QueueFactory.Instance.BuildQueue(this.Path)) 
{ 
    System.Messaging.Message message = new System.Messaging.Message 
    { 
     Body = body, 
     Formatter = new BinaryMessageFormatter(), 
     TimeToBeReceived = this.ExpirationMinutes 
    }; 

    MessageQueueTransaction transaction = new MessageQueueTransaction(); 

    try 
    { 
     transaction.Begin(); 
     queue.Send(message, label, transaction); 
     transaction.Commit(); 
    } 
    catch(System.Exception e) 
    { 
     transaction.Abort(); 
     throw e; 
    } 
    finally 
    { 
     transaction.Dispose(); 
    } 
} 
+0

Potrebbe funzionare o meno, ma mi piacerebbe capire perché tutto questo accade all'improvviso. – goalie7960

+0

C'è una possibilità che la transazione possa rilevare l'errore che il processo senza transazione non ha. – ic3b3rg

+0

Le code dei messaggi devono essere configurate specificatamente come transazionali o non transazionali: se non sono transazionali, il codice non funzionerà se si tenta di aprire una transazione su di esse. Puoi controllare la coda nella gestione del computer per vedere se è transazionale. – penguat

Problemi correlati