0

I've suddenly started getting intermittent NRE's with the following stack:

at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at FileHelpers.RecordInfo.RecordInfoFactory.Resolve(Type type)
at FileHelpers.RecordInfo.Resolve(Type type)
at FileHelpers.EngineBase..ctor(Type recordType, Encoding encoding)
at FileHelpers.EngineBase..ctor(Type recordType)
at FileHelpers.EventEngineBase`1..ctor(Type recordType)
at FileHelpers.FileHelperAsyncEngine`1..ctor()
...

The line throwing is:

FileHelperAsyncEngine<MicrosoftAdCenterGenericKeywordReportData> engine = new FileHelperAsyncEngine<MicrosoftAdCenterGenericKeywordReportData>();

where MicrosoftAdCenterGenericKeywordReportData is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using FileHelpers;

namespace pecom.Common.Entities
{
    [IgnoreFirst(11)]
    [IgnoreLast(1)]
    [IgnoreEmptyLines()]
    [DelimitedRecord(",")]
    public class MicrosoftAdCenterGenericKeywordReportData
    {
        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string KeywordId;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string AdGroupId;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string AdGroupName;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string AverageCpc;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string AverageCpm;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string AveragePosition;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string CampaignId;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string Clicks;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string ConversionRate;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string Conversions;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string Spend;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string Ctr;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string Impressions;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string Keyword;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string QualityScore;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string TimePeriod;

        [FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
        public string CurrentMaxCpc;
    }
}

Any pointers appreciated and apologies for the use of "intermittent" - I'm having real trouble tying this one down. This is with FileHelpers 2.9.9. Note that the code is multi-threaded via Parallel.Invoke. I eyeballed the FileHelpers FileHelpers.RecordInfo.Resolve method and it appears to be at least designed to be thread-safe (I include below for convenience).

Many thanks, Pete

/// <summary>
/// Return the record information for the type
/// </summary>
/// <param name="type">Type we want settings for</param>
/// <remarks>Threadsafe</remarks>
/// <returns>Record Information (settings and functions)</returns>
public static IRecordInfo Resolve(Type type)
{
    RecordInfo res;

    lock (type) {
        lock (mRecordInfoCache) {
            if (mRecordInfoCache.TryGetValue(type, out res))
                return (IRecordInfo) res.Clone();
        }

        // class check cache / lock / check cache  and create if null algorythm

        res = new RecordInfo(type);
        lock (mRecordInfoCache) {
            if (!mRecordInfoCache.ContainsKey(type))
                mRecordInfoCache.Add(type, res);
        }

        return (IRecordInfo) res.Clone();
    }
}
}
sming
  • 801
  • 2
  • 12
  • 25
  • 1
    Update: I've wrapped all calls (there are 6, each parameterized with a different type) to the FileHelperAsyncEngine<> constructor in a lock and can no longer reproduce the exception. As I said though, it looks like the constructor (and it's callee's) are intended to be thread safe. – sming Oct 30 '14 at 16:44
  • A.N.Other update: as to why it's suddenly started happening, I just realised that it coincided with my switch from VS 2012 to VS 2013. – sming Oct 30 '14 at 16:46
  • It appears that you are accessing a `Dictionary` from multiple threads, which isn't thread-safe on its own. – Yuval Itzchakov Oct 30 '14 at 16:51
  • @YuvalItzchakov yes but the method using the Dictionary is designed to be thread-safe, from first appearances. – sming Oct 30 '14 at 17:55
  • How is the dictiobary being initialized? – Yuval Itzchakov Oct 30 '14 at 18:01
  • I just see this question, can you tellme if with the new version 3.1 removing the locks you can reproduce it ? If so I will investigate it, thanks !! – Marcos Meli Aug 10 '15 at 02:51

0 Answers0