2011-07-11 37 views
2

所以我今天遇到了一個奇怪的問題 - 我在鎖的關鍵部分內創建了一個實例,當我手動拖動下一行來執行時,它會拋出一個空引用異常。爲了說明:使用導致空引用的構造函數進行鎖定?

public class SearchEngineOptimizationParser 
{ 
    protected static ConcurrentDictionary<string, SearchEngineOptimizationInfo> _referralInformation = null; 
    protected static DateTime _lastRecordingDate; 
    protected static object _lockRecordingObject = new object(); 

    protected static Dictionary<string, string> _searchProviderLookups = null; 

    static SearchEngineOptimizationParser() 
    { 
     _referralInformation = new ConcurrentDictionary<string, SearchEngineOptimizationInfo>(); 
     _lastRecordingDate = DateTime.Now; 

     _searchProviderLookups = new Dictionary<string, string>(); 
     _searchProviderLookups.Add("google.com", "q"); 
     _searchProviderLookups.Add("yahoo.com", "p"); 
     _searchProviderLookups.Add("bing.com", "q"); 
    } 

    public SearchEngineOptimizationParser() 
    { 

    } 

    public virtual void ParseReferrer(Uri requestUrl, NameValueCollection serverVariables, ISession session) 
    { 
     string corePath = requestUrl.PathAndQuery.SmartSplit('?')[0].ToLower(); 

     string referrer = serverVariables["HTTP_REFERER"]; 

     if (!string.IsNullOrWhiteSpace(referrer)) 
     { 
      NameValueCollection queryString = HttpUtility.ParseQueryString(referrer); 

      string dictionaryKey = session.AffiliateID + "|" + corePath; 

      foreach (var searchProvider in _searchProviderLookups) 
      { 
       if (referrer.Contains(searchProvider.Key)) 
       { 
        if (queryString[searchProvider.Value] != null) 
        { 
         string keywords = queryString[searchProvider.Value]; 

         SearchEngineOptimizationInfo info = new SearchEngineOptimizationInfo 
         { 
          Count = 1, 
          CorePath = corePath, 
          AffiliateId = session.AffiliateID, 
          Keywords = keywords 
         }; 

         _referralInformation.AddOrUpdate(dictionaryKey, info, (key, oldValue) => 
         { 
          oldValue.Count++; 
          return oldValue; 
         }); 

         break; 
        } 
       } 
      } 
     } 

     if (DateTime.Now > _lastRecordingDate.AddHours(1)) 
     { 
      lock (_lockRecordingObject) 
      { 
       if (DateTime.Now > _lastRecordingDate.AddHours(1)) 
       { 
        SearchEngineKeywordRepository repository = new SearchEngineKeywordRepository(); 

        List<KeyValuePair<string, SearchEngineOptimizationInfo>> currentInfo = _referralInformation.ToList(); 

        Action logData =() => 
        { 
         foreach (var item in currentInfo) 
          repository.LogKeyword(item.Value); 
        }; 

        Thread logThread = new Thread(new ThreadStart(logData)); 
        logThread.Start(); 

        _lastRecordingDate = DateTime.Now; 
        _referralInformation.Clear(); 
       } 
      } 
     } 
    } 

編輯:實時更新對象

public class SearchEngineKeywordRepository 
{ 
    public virtual void LogKeyword(SearchEngineOptimizationInfo keywordInfo) 
    { 
     LogSearchEngineKeywords procedure = new LogSearchEngineKeywords(); 
     procedure.Execute(keywordInfo.CorePath, keywordInfo.AffiliateId, keywordInfo.Keywords, keywordInfo.Count); 
    } 
} 

的一般模式是,我想要做的只是每一個小時這個「東西」(網站中的應用程序,獲取了大量的上下文的交通)。我會斷言我的第一個if語句,然後在第二個if語句內執行下一行來執行。這樣做時,初始化SomeObject實例的行爲將導致空引用異常。它有一個完全100%的默認構造函數 - 我甚至沒有指定一個。

但是,當我讓代碼自然通過時,它會執行沒有問題。出於某種原因,當我跳過鎖定調用進入關鍵部分以僅測試運行該代碼時,它似乎導致了各種錯誤。

我很想知道這是爲什麼;我知道lock關鍵字只是一個Monitor.Enter(o) try/finally塊的語法糖,但似乎是在調用構造函數時發生了其他事情。

任何人有任何想法?

編輯:我已經添加了實際的代碼。我可以隨意重現這一點,但我仍然不明白爲什麼會發生這種情況。我試圖將這些代碼複製到另一個解決方案,並且問題似乎沒有發生。

+0

你能後的調用堆棧,並在本例中指出(通過評論)在拋出異常

(離開lock範圍時有_lockRecordingObject設置爲NULL導致ArgumentNullException)?這似乎是某種競爭條件。 –

回答

1

我試圖重現你的情況,但正如我所料,我不能。我已經嘗試了2.0和4.0運行時,在32位和64位模式下(調試有時在x64下的行爲不同)。

顯示的代碼是否簡化了?你檢查了你所有的假設嗎?我知道你跳過3行代碼,if語句和鎖?在這種情況下,即使將鎖對象設置爲null也不會導致您描述的異常。

+0

我嘗試了一個新的視覺工作室解決方案,但我也無法重現它。也許我只需要反編譯當前代碼與Reflector或其他東西... – Tejs

+0

我已經添加了完整的真實代碼。仍然在研究爲什麼會發生這種情況 - 雖然並不重要(因爲生產不會繞過下一行),但我很想知道爲什麼。 – Tejs

+0

標記爲答覆,謝謝你的嘗試! – Tejs

相關問題