6

I have a website that uses MSMQ on a remote server to queue pending e-mails. I am able to write the message to the queue, and then call dispose on the queue. The queue still gets the message, but sometime later the GC comes along and tries to clean up and it causes IIS to crash. This is what I see in the event log:

Exception: System.NullReferenceException

Message: Object reference not set to an instance of an object.

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

This code has been running fine for years, but it just started acting up recently. I have rebooting all the servers to troubleshoot it, but that does not help.

Edit 1

Here is the code that is sending the messages. QueueFactory is just a singleton that has a lock around creating a 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);
}

There is a try-catch around this code, and I know it never makes it into the catch block. I'm beginning to think this was caused when the entire application was upgraded from .NET 3.5 to .NET 4.0. However it started occurring sporadically, but now it happens every time I write a message to the queue.

Edit 2

Here is the code for BuildQueue

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

1 回答 1

0

尝试使用事务:

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();
    }
}
于 2013-01-11T14:53:07.987 回答