예제 #1
0
        /// <summary>
        /// Use in place of CollectionChanged Adder
        /// </summary>
        /// <param name="objTag">Tag to associate with added delegate</param>
        /// <param name="funcDelegateToAdd">Delegate to add to CollectionChanged</param>
        /// <returns>True if delegate was successfully added, false if a delegate already exists with the associated tag.</returns>
        public async ValueTask <bool> AddTaggedCollectionChangedAsync(object objTag, NotifyCollectionChangedEventHandler funcDelegateToAdd)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                (bool blnSuccess, HashSet <NotifyCollectionChangedEventHandler> setFuncs)
                    = await _dicTaggedAddedDelegates.TryGetValueAsync(objTag);

                if (!blnSuccess)
                {
                    setFuncs = new HashSet <NotifyCollectionChangedEventHandler>();
                    await _dicTaggedAddedDelegates.AddAsync(objTag, setFuncs);
                }

                if (setFuncs.Add(funcDelegateToAdd))
                {
                    base.CollectionChanged += funcDelegateToAdd;
                    return(true);
                }
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
            Utils.BreakIfDebug();
            return(false);
        }
예제 #2
0
        /// <summary>
        /// Adds a key/value pair to the dictionary if the key does not already exist, or to update a key/value pair in the dictionary if the key already exists.
        /// </summary>
        /// <param name="key">The key to be added or whose value should be updated</param>
        /// <param name="addValue">The value to be added for an absent key</param>
        /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on the key's existing value</param>
        /// <param name="token">Cancellation token to listen to.</param>
        /// <returns>The new value for the key. This will be either be addValue (if the key was absent) or the result of updateValueFactory (if the key was present).</returns>
        public async ValueTask <TValue> AddOrUpdateAsync(TKey key, TValue addValue, Func <TKey, TValue, TValue> updateValueFactory, CancellationToken token = default)
        {
            using (await EnterReadLock.EnterAsync(LockObject, token))
            {
                IAsyncDisposable objLocker;
                if (_dicData.TryGetValue(key, out TValue objExistingValue))
                {
                    TValue objNewValue = updateValueFactory(key, objExistingValue);
                    objLocker = await LockObject.EnterWriteLockAsync(token);

                    try
                    {
                        token.ThrowIfCancellationRequested();
                        _dicData[key] = objNewValue;
                    }
                    finally
                    {
                        await objLocker.DisposeAsync();
                    }
                    return(objNewValue);
                }
                objLocker = await LockObject.EnterWriteLockAsync(token);

                try
                {
                    token.ThrowIfCancellationRequested();
                    _dicData.Add(key, addValue);
                }
                finally
                {
                    await objLocker.DisposeAsync();
                }
                return(addValue);
            }
        }
예제 #3
0
        /// <summary>
        /// Adds a key/value pair to the dictionary if the key does not already exist, or to update a key/value pair in the dictionary if the key already exists.
        /// </summary>
        /// <param name="key">The key to be added or whose value should be updated</param>
        /// <param name="addValue">The value to be added for an absent key</param>
        /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on the key's existing value</param>
        /// <returns>The new value for the key. This will be either be addValue (if the key was absent) or the result of updateValueFactory (if the key was present).</returns>
        public async ValueTask <TValue> AddOrUpdateAsync(TKey key, TValue addValue, Func <TKey, TValue, TValue> updateValueFactory)
        {
            using (await EnterReadLock.EnterAsync(LockObject))
            {
                IAsyncDisposable objLocker;
                if (_dicData.TryGetValue(key, out TValue objExistingValue))
                {
                    TValue objNewValue = updateValueFactory(key, objExistingValue);
                    objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

                    try
                    {
                        _dicData[key] = objNewValue;
                    }
                    finally
                    {
                        await objLocker.DisposeAsync().ConfigureAwait(false);
                    }
                    return(objNewValue);
                }
                objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

                try
                {
                    _dicData.Add(key, addValue);
                }
                finally
                {
                    await objLocker.DisposeAsync().ConfigureAwait(false);
                }
                return(addValue);
            }
        }
예제 #4
0
        /// <inheritdoc cref="List{T}.Sort()" />
        public async ValueTask SortAsync()
        {
            using (await EnterReadLock.EnterAsync(LockObject))
            {
                if (_setData.Comparer is IComparer <T> comparer)
                {
                    IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

                    try
                    {
                        _lstOrderedData.Sort(comparer);
                    }
                    finally
                    {
                        await objLocker.DisposeAsync();
                    }
                }
                else
                {
                    IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

                    try
                    {
                        _lstOrderedData.Sort();
                    }
                    finally
                    {
                        await objLocker.DisposeAsync();
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Use in place of CollectionChanged Subtract
        /// </summary>
        /// <param name="objTag">Tag of delegate to remove from CollectionChanged</param>
        /// <returns>True if a delegate associated with the tag was found and deleted, false otherwise.</returns>
        public async ValueTask <bool> RemoveTaggedCollectionChangedAsync(object objTag)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                (bool blnSuccess, HashSet <NotifyCollectionChangedEventHandler> setFuncs)
                    = await _dicTaggedAddedDelegates.TryGetValueAsync(objTag);

                if (!blnSuccess)
                {
                    Utils.BreakIfDebug();
                    return(false);
                }

                foreach (NotifyCollectionChangedEventHandler funcDelegateToRemove in setFuncs)
                {
                    base.CollectionChanged -= funcDelegateToRemove;
                }

                setFuncs.Clear();
                return(true);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #6
0
        /// <inheritdoc cref="List{T}.Insert" />
        public async ValueTask InsertAsync(int index, T item)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _lstData.Insert(index, item);
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #7
0
        public async ValueTask AddRangeAsync(IEnumerable <T> collection)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                _lstData.AddRange(collection);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #8
0
        /// <inheritdoc cref="List{T}.RemoveAll" />
        public async ValueTask <int> RemoveAllAsync(Task <Predicate <T> > match)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                return(_lstData.RemoveAll(await match));
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #9
0
        /// <inheritdoc cref="List{T}.Sort(Comparison{T})" />
        public async ValueTask SortAsync(Comparison <T> comparison)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                _lstOrderedData.Sort(comparison);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #10
0
        public async ValueTask AddAsync(TKey key, TValue value)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _dicData.Add(key, value);
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #11
0
        /// <inheritdoc cref="List{T}.RemoveRange" />
        public async ValueTask RemoveRangeAsync(int index, int count)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _lstData.RemoveRange(index, count);
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #12
0
        /// <inheritdoc cref="List{T}.TrimExcess" />
        public async ValueTask TrimExcessAsync()
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _lstData.TrimExcess();
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #13
0
        /// <inheritdoc cref="List{T}.Reverse(int, int)" />
        public async ValueTask ReverseAsync(int index, int count)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                _lstOrderedData.Reverse(index, count);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #14
0
        /// <inheritdoc cref="List{T}.InsertRange" />
        public async ValueTask InsertRangeAsync(int index, IEnumerable <T> collection)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _lstData.InsertRange(index, collection);
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #15
0
        /// <inheritdoc cref="List{T}.Sort(IComparer{T})" />
        public async ValueTask SortAsync(IComparer <T> comparer)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _lstData.Sort(comparer);
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #16
0
        /// <inheritdoc cref="List{T}.Sort(int, int, IComparer{T})" />
        public async ValueTask SortAsync(int index, int count, IComparer <T> comparer)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                _lstOrderedData.Sort(index, count, comparer);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #17
0
        /// <inheritdoc cref="List{T}.Sort()" />
        public async ValueTask SortAsync()
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                _lstData.Sort();
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #18
0
        public async ValueTask AddAsync(T item)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _lstData.Add(item);
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
        }
        /// <inheritdoc cref="List{T}.Remove(T)" />
        public async ValueTask <bool> RemoveAsync(T item)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                return(_lstData.Remove(item));
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
        /// <inheritdoc cref="EnhancedObservableCollection{T}.RemoveAt" />
        public async ValueTask RemoveAtAsync(int index)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                _lstData.RemoveAt(index);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #21
0
        public async ValueTask AddAsync(TKey key, TValue value, CancellationToken token = default)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync(token);

            try
            {
                token.ThrowIfCancellationRequested();
                _dicData.Add(key, value);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #22
0
        public async ValueTask RemoveAtAsync(int index)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                T objToRemove = _lstOrderedData[index];
                if (_setData.Remove(objToRemove))
                {
                    _lstOrderedData.RemoveAt(index);
                }
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #23
0
        public async ValueTask InsertAsync(int index, T item)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                if (!_setData.Add(item))
                {
                    return;
                }
                _lstOrderedData.Insert(index, item);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #24
0
        /// <summary>
        /// Uses the specified functions to remove a key/value pair from the dictionary if the key exists and passes a condition, or to update a key/value pair in the dictionary if the key exists but does not.
        /// </summary>
        /// <param name="key">The key to be removed or whose value should be updated</param>
        /// <param name="removalConditionFunc">The function used to check if a key should be removed or updated.</param>
        /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on the key's existing value</param>
        public async ValueTask <bool> RemoveOrUpdateAsync(TKey key, Func <TKey, TValue, bool> removalConditionFunc,
                                                          Func <TKey, TValue, TValue> updateValueFactory)
        {
            bool blnReturn;

            using (await EnterReadLock.EnterAsync(LockObject))
            {
                if (_dicData.TryGetValue(key, out TValue objExistingValue))
                {
                    blnReturn = removalConditionFunc(key, objExistingValue);
                    if (blnReturn)
                    {
                        IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

                        try
                        {
                            blnReturn = _dicData.Remove(key);
                        }
                        catch
                        {
                            await objLocker.DisposeAsync().ConfigureAwait(false);
                        }
                    }
                    if (!blnReturn) // Not an else in case we somehow fail at removing a key that still passes the condition
                    {
                        IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

                        try
                        {
                            _dicData[key] = updateValueFactory(key, objExistingValue);
                        }
                        catch
                        {
                            await objLocker.DisposeAsync().ConfigureAwait(false);
                        }
                    }
                }
                else
                {
                    blnReturn = false;
                }
            }
            return(blnReturn);
        }
예제 #25
0
        public async ValueTask <bool> TryAddAsync(TKey key, TValue value)
        {
            // Immediately enter a write lock to prevent attempted reads until we have either added the item we want to add or failed to do so
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                if (_dicData.ContainsKey(key))
                {
                    return(false);
                }
                _dicData.Add(key, value);
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
            return(true);
        }
예제 #26
0
        public async ValueTask <bool> TryAddAsync(TKey key, TValue value, CancellationToken token = default)
        {
            // Immediately enter a write lock to prevent attempted reads until we have either added the item we want to add or failed to do so
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync(token);

            try
            {
                token.ThrowIfCancellationRequested();
                if (_dicData.ContainsKey(key))
                {
                    return(false);
                }
                _dicData.Add(key, value);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
            return(true);
        }
예제 #27
0
        /// <inheritdoc />
        public async ValueTask DisposeAsync()
        {
            if (_blnIsDisposed)
            {
                return;
            }
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync().ConfigureAwait(false);

            try
            {
                _blnIsDisposed = true;
                _imgMugshot?.Dispose();
                _tskRunningDownloadTask?.Dispose();
                await _dicMyPluginData.DisposeAsync();
            }
            finally
            {
                await objLocker.DisposeAsync().ConfigureAwait(false);
            }
            await LockObject.DisposeAsync();
        }
예제 #28
0
        /// <inheritdoc cref="List{T}.Insert" />
        public override async ValueTask InsertAsync(int index, T item)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                int intExistingIndex = await IndexOfAsync(item);

                if (intExistingIndex == -1)
                {
                    await base.InsertAsync(index, item);
                }
                else
                {
                    await MoveAsync(intExistingIndex, Math.Min(index, await CountAsync - 1));
                }
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
        /// <inheritdoc cref="List{T}.Insert" />
        public override async ValueTask InsertAsync(int index, T item)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                if (index >= _intMaxSize)
                {
                    return;
                }
                int intCount = await CountAsync;
                while (intCount >= _intMaxSize)
                {
                    await RemoveAtAsync(intCount - 1);

                    intCount = await CountAsync;
                }
                await base.InsertAsync(index, item);
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }
예제 #30
0
        private async Task <bool> LoadFromFileCoreAsync(bool blnSync, string strFile)
        {
            IAsyncDisposable objLocker = await LockObject.EnterWriteLockAsync();

            try
            {
                _tskRunningDownloadTask = null;
                string         strErrorText = string.Empty;
                XPathNavigator xmlSourceNode;
                if (!File.Exists(strFile))
                {
                    xmlSourceNode = null;
                    strErrorText  = blnSync
                                    // ReSharper disable once MethodHasAsyncOverload
                        ? LanguageManager.GetString("MessageTitle_FileNotFound")
                        : await LanguageManager.GetStringAsync("MessageTitle_FileNotFound");
                }
                else
                {
                    // If we run into any problems loading the character cache, fail out early.
                    try
                    {
                        XPathDocument xmlDoc = blnSync ? LoadXPathDocument() : await Task.Run(LoadXPathDocument);

                        XPathDocument LoadXPathDocument()
                        {
                            using (StreamReader objStreamReader = new StreamReader(strFile, Encoding.UTF8, true))
                            {
                                using (XmlReader objXmlReader =
                                           XmlReader.Create(objStreamReader, GlobalSettings.SafeXmlReaderSettings))
                                {
                                    return(new XPathDocument(objXmlReader));
                                }
                            }
                        }

                        xmlSourceNode = blnSync
                                        // ReSharper disable once MethodHasAsyncOverload
                            ? xmlDoc.CreateNavigator().SelectSingleNodeAndCacheExpression("/character")
                            : await xmlDoc.CreateNavigator().SelectSingleNodeAndCacheExpressionAsync("/character");
                    }
                    catch (Exception ex)
                    {
                        xmlSourceNode = null;
                        strErrorText  = ex.ToString();
                    }
                }

                if (xmlSourceNode != null)
                {
                    if (blnSync)
                    {
                        // ReSharper disable MethodHasAsyncOverload
                        _strDescription    = xmlSourceNode.SelectSingleNodeAndCacheExpression("description")?.Value;
                        _strBuildMethod    = xmlSourceNode.SelectSingleNodeAndCacheExpression("buildmethod")?.Value;
                        _strBackground     = xmlSourceNode.SelectSingleNodeAndCacheExpression("background")?.Value;
                        _strCharacterNotes = xmlSourceNode.SelectSingleNodeAndCacheExpression("notes")?.Value;
                        _strGameNotes      = xmlSourceNode.SelectSingleNodeAndCacheExpression("gamenotes")?.Value;
                        _strConcept        = xmlSourceNode.SelectSingleNodeAndCacheExpression("concept")?.Value;
                        _strKarma          = xmlSourceNode.SelectSingleNodeAndCacheExpression("totalkarma")?.Value;
                        _strMetatype       = xmlSourceNode.SelectSingleNodeAndCacheExpression("metatype")?.Value;
                        _strMetavariant    = xmlSourceNode.SelectSingleNodeAndCacheExpression("metavariant")?.Value;
                        _strPlayerName     = xmlSourceNode.SelectSingleNodeAndCacheExpression("playername")?.Value;
                        _strCharacterName  = xmlSourceNode.SelectSingleNodeAndCacheExpression("name")?.Value;
                        _strCharacterAlias = xmlSourceNode.SelectSingleNodeAndCacheExpression("alias")?.Value;
                        _blnCreated        = xmlSourceNode.SelectSingleNodeAndCacheExpression("created")?.Value
                                             == bool.TrueString;
                        _strEssence = xmlSourceNode.SelectSingleNodeAndCacheExpression("totaless")?.Value;
                        // ReSharper restore MethodHasAsyncOverload
                    }
                    else
                    {
                        _strDescription    = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("description"))?.Value;
                        _strBuildMethod    = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("buildmethod"))?.Value;
                        _strBackground     = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("background"))?.Value;
                        _strCharacterNotes = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("notes"))?.Value;
                        _strGameNotes      = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("gamenotes"))?.Value;
                        _strConcept        = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("concept"))?.Value;
                        _strKarma          = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("totalkarma"))?.Value;
                        _strMetatype       = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("metatype"))?.Value;
                        _strMetavariant    = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("metavariant"))?.Value;
                        _strPlayerName     = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("playername"))?.Value;
                        _strCharacterName  = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("name"))?.Value;
                        _strCharacterAlias = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("alias"))?.Value;
                        _blnCreated        = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("created"))?.Value == bool.TrueString;
                        _strEssence        = (await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("totaless"))?.Value;
                    }

                    string strSettings
                        = (blnSync
                           // ReSharper disable once MethodHasAsyncOverload
                              ? xmlSourceNode.SelectSingleNodeAndCacheExpression("settings")
                              : await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("settings"))?.Value
                          ?? string.Empty;
                    if (!string.IsNullOrEmpty(strSettings))
                    {
                        (bool blnSuccess, CharacterSettings objSettings)
                            = await SettingsManager.LoadedCharacterSettings.TryGetValueAsync(strSettings);

                        if (blnSuccess)
                        {
                            _strSettingsFile = objSettings.DisplayName;
                        }
                        else
                        {
                            string strTemp = blnSync
                                             // ReSharper disable once MethodHasAsyncOverload
                                ? LanguageManager.GetString("MessageTitle_FileNotFound") +
                                             // ReSharper disable once MethodHasAsyncOverload
                                             LanguageManager.GetString("String_Space")
                                : await LanguageManager.GetStringAsync("MessageTitle_FileNotFound") +
                                             await LanguageManager.GetStringAsync("String_Space");

                            _strSettingsFile = strTemp + '[' + strSettings + ']';
                        }
                    }
                    else
                    {
                        _strSettingsFile = string.Empty;
                    }

                    string strMugshotBase64
                        = (blnSync
                           // ReSharper disable once MethodHasAsyncOverload
                              ? xmlSourceNode.SelectSingleNodeAndCacheExpression("mugshot")
                              : await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("mugshot"))?.Value
                          ?? string.Empty;
                    if (string.IsNullOrEmpty(strMugshotBase64))
                    {
                        XPathNavigator xmlMainMugshotIndex = blnSync
                                                             // ReSharper disable once MethodHasAsyncOverload
                            ? xmlSourceNode.SelectSingleNodeAndCacheExpression("mainmugshotindex")
                            : await xmlSourceNode.SelectSingleNodeAndCacheExpressionAsync("mainmugshotindex");

                        if (xmlMainMugshotIndex != null &&
                            int.TryParse(xmlMainMugshotIndex.Value, out int intMainMugshotIndex) &&
                            intMainMugshotIndex >= 0)
                        {
                            XPathNodeIterator xmlMugshotList = blnSync
                                                               // ReSharper disable once MethodHasAsyncOverload
                                ? xmlSourceNode.SelectAndCacheExpression("mugshots/mugshot")
                                : await xmlSourceNode.SelectAndCacheExpressionAsync("mugshots/mugshot");

                            if (xmlMugshotList.Count > intMainMugshotIndex)
                            {
                                int intIndex = 0;
                                foreach (XPathNavigator xmlMugshot in xmlMugshotList)
                                {
                                    if (intMainMugshotIndex == intIndex)
                                    {
                                        strMugshotBase64 = xmlMugshot.Value;
                                        break;
                                    }

                                    ++intIndex;
                                }
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(strMugshotBase64))
                    {
                        _imgMugshot?.Dispose();
                        if (blnSync)
                        {
                            // ReSharper disable once MethodHasAsyncOverload
                            using (Image imgMugshot = strMugshotBase64.ToImage())
                                // ReSharper disable once MethodHasAsyncOverload
                                _imgMugshot = imgMugshot.GetCompressedImage();
                        }
                        else
                        {
                            using (Image imgMugshot = await strMugshotBase64.ToImageAsync())
                                _imgMugshot = await imgMugshot.GetCompressedImageAsync();
                        }
                    }
                }
                else
                {
                    _strErrorText = strErrorText;
                }

                _strFilePath = strFile;
                if (!string.IsNullOrEmpty(strFile))
                {
                    int last = strFile.LastIndexOf(Path.DirectorySeparatorChar) + 1;
                    if (strFile.Length > last)
                    {
                        _strFileName = strFile.Substring(last);
                    }
                }

                return(string.IsNullOrEmpty(strErrorText));
            }
            finally
            {
                await objLocker.DisposeAsync();
            }
        }