2009-07-17 64 views
0

好的我有一個靜態類,它有兩個靜態成員,一個字符串和一個布爾值。
公共靜態方法根據傳入參數的狀態爲這些成員分配值。靜態成員不保留指定的值

然後調用一個私有靜態方法來處理靜態成員。

問題是,雖然布爾值保留它在公共函數中設置的值,但字符串不會;它默認回到它的初始值。爲什麼是這樣?
簡化代碼如下。

static class MessageHandler 
{ 
    private static String m_messageToSend = String.Empty; 
    private static bool m_requiresACK = false; 


    public static void Send(String message) 
    { 
     //formatting etc (actual method sets more fields) 
     m_messageToSend = message; 
     m_requiresACK = true; 

     Send(); 
    } 

    private void static Send() 
    { 
     SendMessageDelegate sendDelegate = DoSend; 
     //At this point m_requiresACK remains true but m_messageToSend does not 
     //hold value of message; it is empty. 
     IAsyncResult ar = sendDelegate.BeginInvoke(m_messageToSend, m_requiresACK); 


     //rest of function 
    } 
} 

//some other class 
MessageHandler.Send("Hello"); 
+0

確定它在Send(字符串)方法中正確分配。簡化tge代碼時你忘了提及什麼嗎? – 2009-07-17 12:29:18

+1

爲什麼這是一個靜態類? – devio 2009-07-17 12:35:50

+0

德維奧 - 也許它不應該,我還在學習。這似乎是最優雅的解決方案,並不需要創建對象。類名稱不是很好,需要更改 - MessageHandler可能是因爲它將它轉發。 MessageHandler.Send(消息)。 – Kildareflare 2009-07-17 13:08:56

回答

4

此代碼的線程「unsafetyness」可能是問題,因爲其他線程可能會調用Send(string),而您的線程當前處於同一方法的中間。我建議以下重寫消息類:

static class Message 
{ 
    public static void Send(String message) 
    { 
     Send(message, true); 
    } 

    private void static Send(string messageToSend, bool requiresACK) 
    { 
     SendMessageDelegate sendDelegate = DoSend; 
     IAsyncResult ar = sendDelegate.BeginInvoke(messageToSend, requiresACK); 

     //rest of function 
    } 
} 
+0

彼得 - 這似乎已經解決了這個問題。正如我剛剛使用成員直接,因爲我最近傾向於這一點,而不是傳遞負載參數(實際上超過列出)。然而,當然在這個例子中,傳遞參數看起來更有意義 - 馬匹用於課程。 – Kildareflare 2009-07-17 13:01:29

2

這是最有可能是由於另一個線程調用

Message.Send(""); 

或您的AppDomain被卸載。沒有更多的信息,很難肯定地說。

0

如果一個字段保持相同的值,而另一個字段保持不變,我會感到非常驚訝。

如果這是一個Web應用程序,這可能發生在應用程序被回收的情況下。

2

您有一些巨大的線程安全問題。如果你真的想這個靜態的,有一個厚臉皮修復:

[ThreadStatic] 
private static String m_messageToSend = String.Empty; 
[ThreadStatic] 
private static bool m_requiresACK = false; 

這現在作爲靜態的,而是每個線程。危機避免了;但是這有點......好吧,我會盡量避免需要,我自己 - 但它會正常工作。

重要:初始值設定項是每個線程,而不是每個請求;因爲你的線程很可能會被重用,所以你應該確保在嘗試使用它之前初始化狀態,否則你可能會有舊垃圾。

0

我在你的評論中看到,在第一行之後,私有變量是空的而不是保存參數的值。只要您點擊Send()的第一行,這是否爲真?編寫一個調用Message.Send(「Hello World」)的單元測試或簡單測試工具;並在輸出中進行斷言。將此與您的調用代碼庫隔離可以讓您瞭解它是您的Message類的行爲異常,還是消費者發送錯誤/意外的數據。另外,除非你的//函數的其餘部分包括重置你的布爾值,否則在發送第一條消息之後它總是成立的。