DeviceDetector.NET
DeviceDetector.NET copied to clipboard
Concurrency Issue
Code USed: Startup.cs
DeviceDetector.SetVersionTruncation(VersionTruncation.VERSION_TRUNCATION_NONE);
var userAgent = context.Request.Headers["User-Agent"];
var deviceDetector = new DeviceDetector(userAgent);
deviceDetector.Parse();
Issue encounter: System.InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
at System.Collections.Generic.Dictionary`2.ContainsKey(TKey key)
at DeviceDetectorNET.Cache.DictionaryCache.Contains(String id)
at DeviceDetectorNET.Cache.DictionaryCache.Fetch(String id)
at DeviceDetectorNET.Parser.ParserAbstract`2.GetRegexes()
at DeviceDetectorNET.Parser.Client.LibraryParser..ctor()
at DeviceDetectorNET.Parser.Client.ClientType.get_Library()
at DeviceDetectorNET.DeviceDetector.AddClientsParser()
at DeviceDetectorNET.DeviceDetector..ctor(String userAgent)
I'm getting the same issue, somewhat random. Aside from restarting the process, how can I avoid getting this error? Once its in a corrupt state, it seems only a restart can solve it.
Same thing, this bug suddenly appeared today.
In the meantime I've just implemented a cache check with concurrent dictionary before making a call to DeviceDetectorNET
@cpkuo care to share the code? :)
Sure, there is still the possibility that DeviceDetector will write to it's internal cache collection on concurrent requests but this seems to have helped me in a high load environment. I wonder if setting a new instance of DictonaryCache on each request in combination with the custom ConcurrentDictionary cache will completely eliminate the error. I will need to review the source code at some point, in the meantime here is some code.
`private static ConcurrentDictionary<string, DeviceInfo> cache = new ConcurrentDictionary<string, DeviceInfo>(); private static DictionaryCache dicationaryCache = new DictionaryCache();
public DeviceInfo Get(string userAgent)
{
if (cache.ContainsKey(userAgent))
{
return cache[userAgent];
}
//Domain class
var info = new DeviceInfo();
DeviceDetector.SetVersionTruncation(VersionTruncation.VERSION_TRUNCATION_NONE);
var dd = new DeviceDetector(userAgent);
dd.SetCache(dicationaryCache);
dd.Parse();
var client = dd.GetClient();
//Transfer result into domain class DeviceInfo
// .......
cache.TryAdd(userAgent, info);
return info;
}`
So I went into the source code to match up with the stack trace for this exception and realized I was using a dotnet core version package of DeviceDetector.NET that I don't believe exists anymore. Nuget package manager was not notifying me of updating. So I removed it and started using the latest package of DeviceDetector.NET which now supports the latest .net standard. So far, I have not run into this issue.
This can still happen:
System.InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
at System.Collections.Generic.Dictionary`2.FindValue(TKey key)
at System.Collections.Generic.Dictionary`2.ContainsKey(TKey key)
at DeviceDetectorNET.Cache.DictionaryCache.Contains(String id)
at DeviceDetectorNET.Cache.DictionaryCache.Fetch(String id)
at DeviceDetectorNET.Parser.ParserAbstract`2.GetRegexes()
at DeviceDetectorNET.Parser.Client.MediaPlayerParser..ctor()
at DeviceDetectorNET.Parser.Client.ClientType.get_MediaPlayer()
at DeviceDetectorNET.DeviceDetector.AddClientsParser()
at DeviceDetectorNET.DeviceDetector..ctor(String userAgent)
at
I'm now following the advice to cache userAgents and I set SetVersionTruncation once statically
I did my final fix has having a custom ICache with ConcurrentDictionary instead of just Dictionary