2012-07-05 69 views
0

在C#ASP.NET 3.5 Web應用程序在Windows消息隊列的所有消息,我在一段時間出現以下錯誤一次:零星的錯誤而獲得Windows Server 2003上運行

"Object reference not set to an instance of an object.: at System.Messaging.Interop.MessagePropertyVariants.Unlock() 
    at System.Messaging.Message.Unlock() 
    at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType) 
    at System.Messaging.MessageEnumerator.get_Current() 
    at System.Messaging.MessageQueue.GetAllMessages()". 

的代碼,將引發此行錯誤是:

Message[] msgs = Global.getOutputQueue(mode).GetAllMessages(); 

其中Global.getOutputQueue(mode)給我希望從中獲取郵件的消息隊列。

更新:

Global.getPool(mode).WaitOne(); 
commonClass.log(-1, "Acquired pool: " + mode, "Report ID: " + unique_report_id); 
      ............../* some code / .............. lock(getLock(mode)) { bool yet_to_get = true; int num_retry = 0; do { try { msgs = Global.getOutputQueue(mode).GetAllMessages(); yet_to_get = false; } catch { Global.setOutputQueue(mode); msgs = Global.getOutputQueue(mode).GetAllMessages(); yet_to_get = false; } ++num_retry; } while (yet_to_get && num_retry < 2); } ... / some code*/ 
.... 
finally 
      { 
       commonClass.log(-1, "Released pool: " + mode, "Report ID: " + unique_report_id); 
       Global.getPool(mode).Release(); 
      } 

回答

1

你的描述,建議this thread一個時間問題。我很少創建MessageQueue對象(可能只有一次),並且Global.getOutputQueue(mode)返回一個緩存版本,似乎可能會解決此問題。

編輯:進一步的細節表明你有相反的問題。我建議封裝對消息隊列的訪問,捕獲此異常並在發生異常時重新創建隊列。因此,像這樣的東西替代呼叫Global.getOutputQueue(模式).GetAllMessages():

public void getAllOutputQueueMessages() 
{ 
    try 
    { 
     return queue_.GetAllMessages(); 
    } 
    catch (Exception) 
    { 
     queue_ = OpenQueue(); 
     return queue_.GetAllMessages(); 
    } 
} 

你會發現我沒有保護你的mode功能,但你的想法。當然,你必須複製這個模式來進行你對隊列的其他調用,但僅限於你所做的(不是整個隊列接口)。

+0

Thanks tallseth。 MessageQueue對象已經在Application_Start(Object sender,EventArgs e)中創建。 Global.getOutputQueue(mode)方法只返回它。我錯過了什麼嗎?謝謝。 public static MessageQueue getOutputQueue(char mode) { return(mode =='d')? outputQd:outputQw; } – engg 2012-07-05 22:22:09

+0

聽起來像你可能會遇到相反的問題,一個陳舊的隊列處理。如果可能的話,不要將隊列返回給調用代碼,而是代理您需要的隊列上的方法。然後捕獲此異常,並通過重新創建隊列來處理它,然後再次嘗試。確保不要遞解,但如果事情發生錯誤,你不想要無限循環。 – tallseth 2012-07-05 22:30:35

1

這是一個古老的線程,但谷歌帶我到這裏,所以我會補充我的發現。

我同意用戶:tallseth,這是一個時間問題。

消息隊列創建後,它不是即時可用的。

 try 
     { 
      return _queue.GetAllMessages().Length; 
     } 
     catch (Exception) 
     { 
      System.Threading.Thread.Sleep(4000); 
      return _queue.GetAllMessages().Length; 
     } 

嘗試添加一個暫停,如果您在訪問已知創建的隊列時發現異常。

與此相關的

_logQueuePath = logQueuePath.StartsWith(@".\") ? logQueuePath : @".\" + logQueuePath; 
_queue = new MessageQueue(_logQueuePath); 
MessageQueue.Create(_logQueuePath); 
bool exists = MessageQueue.Exists(_logQueuePath); 

運行MessageQueue.Exists(串nameofQ);方法創建隊列後立即返回false。調用代碼時要小心,例如:

 public void CreateQueue() 
    { 
     if (!MessageQueue.Exists(_logQueuePath)) 
     { 
      MessageQueue.Create(_logQueuePath); 
     } 
    } 

因爲它很可能會拋出異常,說明你正在試圖創建隊列存在。

-edit(對不起,我沒有相關的鏈接,這個新的信息)

,我讀了一個新創建的MessageQueue將返回false上MessageQueue.Exists(QueuePath),直到它已收到至少一信息。

保持這一點以及我之前提到的要點已經使我的代碼可靠運行。

+0

謝謝Tessi。我的代碼最近一直穩定。 – engg 2014-05-23 13:27:23

相關問題