所以今天我遇到了一个奇怪的问题 - 我在一个锁的关键部分内创建了一个简单的实例,当我手动拖动下一行执行时,它会抛出一个空引用异常。举例说明:
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 :(得分:1)
我试图重现你的情况,但正如我所料,我做不到。我在32位和64位模式下尝试过2.0和4.0运行时(调试在x64下的行为有时会有所不同)。
代码是否显示简化?你检查了所有的假设吗?我知道你正在跳过3行代码,if语句和锁定?在这种情况下,即使将lock对象设置为null也不会导致您描述的异常。
(将_lockRecordingObject
设置为null会在离开ArgumentNullException
范围时导致lock