使用构造函数锁定导致空引用?

时间:2011-07-11 16:00:05

标签: c# asp.net exception constructor locking

所以今天我遇到了一个奇怪的问题 - 我在一个锁的关键部分内创建了一个简单的实例,当我手动拖动下一行执行时,它会抛出一个空引用异常。举例说明:

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块的语法糖,但这似乎是在调用构造函数时,还发生了其他事情。

有人有什么想法吗?

编辑:我已经添加了实际代码。我可以随意重现这个,但我仍然不明白为什么会这样。我已经尝试将此代码复制到另一个解决方案,似乎没有出现问题。

1 个答案:

答案 0 :(得分:1)

我试图重现你的情况,但正如我所料,我做不到。我在32位和64位模式下尝试过2.0和4.0运行时(调试在x64下的行为有时会有所不同)。

代码是否显示简化?你检查了所有的假设吗?我知道你正在跳过3行代码,if语句和锁定?在这种情况下,即使将lock对象设置为null也不会导致您描述的异常。

(将_lockRecordingObject设置为null会在离开ArgumentNullException范围时导致lock