所以我今天遇到了一個奇怪的問題 - 我在鎖的關鍵部分內創建了一個實例,當我手動拖動下一行來執行時,它會拋出一個空引用異常。爲了說明:使用導致空引用的構造函數進行鎖定?
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塊的語法糖,但似乎是在調用構造函數時發生了其他事情。
任何人有任何想法?
編輯:我已經添加了實際的代碼。我可以隨意重現這一點,但我仍然不明白爲什麼會發生這種情況。我試圖將這些代碼複製到另一個解決方案,並且問題似乎沒有發生。
你能後的調用堆棧,並在本例中指出(通過評論)在拋出異常
(離開
lock
範圍時有_lockRecordingObject
設置爲NULL導致ArgumentNullException
)?這似乎是某種競爭條件。 –