示例#1
0
        /// <summary>
        ///     Parse the given <paramref name="fileSpec" /> into a <see cref="MSBuildGlob" /> using a given
        ///     <paramref name="globRoot" />.
        /// </summary>
        /// <param name="globRoot">
        ///     The root of the glob.
        ///     The fixed directory part of the glob and the match arguments (<see cref="IsMatch" /> and <see cref="MatchInfo" />)
        ///     will get normalized against this root.
        ///     If empty, the current working directory is used.
        ///     Cannot be null, and cannot contain invalid path arguments.
        /// </param>
        /// <param name="fileSpec">The string to parse</param>
        /// <returns></returns>
        public static MSBuildGlob Parse(string globRoot, string fileSpec)
        {
            ErrorUtilities.VerifyThrowArgumentNull(globRoot, nameof(globRoot));
            ErrorUtilities.VerifyThrowArgumentNull(fileSpec, nameof(fileSpec));
            ErrorUtilities.VerifyThrowArgumentInvalidPath(globRoot, nameof(globRoot));

            if (string.IsNullOrEmpty(globRoot))
            {
                globRoot = Directory.GetCurrentDirectory();
            }

            globRoot = Strings.WeakIntern(FileUtilities.NormalizePath(globRoot).WithTrailingSlash());

            var lazyState = new Lazy <GlobState>(() =>
            {
                FileMatcher.Default.GetFileSpecInfo(
                    fileSpec,
                    out string fixedDirectoryPart,
                    out string wildcardDirectoryPart,
                    out string filenamePart,
                    out bool needsRecursion,
                    out bool isLegalFileSpec,
                    (fixedDirPart, wildcardDirPart, filePart) =>
                {
                    var normalizedFixedPart = NormalizeTheFixedDirectoryPartAgainstTheGlobRoot(fixedDirPart, globRoot);

                    return(normalizedFixedPart, wildcardDirPart, filePart);
                });

                Regex regex = null;
                if (isLegalFileSpec)
                {
                    string matchFileExpression = FileMatcher.RegularExpressionFromFileSpec(fixedDirectoryPart, wildcardDirectoryPart, filenamePart);

                    lock (s_regexCache)
                    {
                        s_regexCache.TryGetValue(matchFileExpression, out regex);
                    }

                    if (regex == null)
                    {
                        // compile the regex since it's expected to be used multiple times
                        Regex newRegex = new Regex(matchFileExpression, FileMatcher.DefaultRegexOptions | RegexOptions.Compiled);
                        lock (s_regexCache)
                        {
                            if (!s_regexCache.TryGetValue(matchFileExpression, out regex))
                            {
                                s_regexCache[matchFileExpression] = newRegex;
                            }
                        }
                        regex ??= newRegex;
                    }
                }
                return(new GlobState(globRoot, fileSpec, isLegalFileSpec, fixedDirectoryPart, wildcardDirectoryPart, filenamePart, needsRecursion, regex));
            },
示例#2
0
        public override async Task InvokeAsync(ILoadingContext <TResult> context, PipeDelegate <TResult> next, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (IsInDesignMode)
            {
                await next(context, cancellationToken);

                return;
            }

            var source = context.Current;

            if (source is string || source is Uri)
            {
                if (MemoryCache.TryGetValue(source, out var cache))
                {
                    context.Result = cache;
                    return;
                }

                await next(context, cancellationToken);

                var result = context.Result;
                if (result != null)
                {
                    MemoryCache[source] = result;
                }

                return;
            }

            await next(context, cancellationToken);
        }
示例#3
0
        /// <inheritdoc />
        public override async Task InvokeAsync(ILoadingContext <TSource> context, LoadingPipeDelegate <TSource> next, CancellationToken cancellationToken = default)
        {
            if (IsInDesignMode)
            {
                await next(context, cancellationToken);

                return;
            }

            var cacheKey = context.Current;

            if (cacheKey is string || cacheKey is Uri)
            {
                if (MemoryCache.TryGetValue(cacheKey, out var cacheValue))
                {
                    context.Current = cacheValue;
                    context.AttachSource(cacheValue);
                    return;
                }

                await next(context, cancellationToken);

                if (context.Current is TSource finalValue)
                {
                    MemoryCache[cacheKey] = finalValue;
                }

                return;
            }

            await next(context, cancellationToken);
        }
示例#4
0
 internal static object GetValue(string varName)
 {
     lock (Variables)
     {
         INodeData tmp;
         Variables.TryGetValue(varName, out tmp);
         return(tmp);
     }
 }
        public void TryGetValue_ReferenceNotFound()
        {
            var dictionary = new WeakValueDictionary <string, string>();

            string v;
            bool   result = dictionary.TryGetValue("x", out v);

            Assert.IsFalse(result);
            Assert.IsNull(v);
            Assert.IsFalse(dictionary.Contains("x"));
        }
示例#6
0
        public void When_item_is_added_Then_it_can_be_retrieved()
        {
            var  dict = new WeakValueDictionary <int, Item>();
            Item item = new Item();

            dict[1] = item;
            bool exists = dict.TryGetValue(1, out item);

            Assert.That(dict.Count, Is.EqualTo(1));
            Assert.That(exists, Is.True);
            Assert.That(item, Is.EqualTo(item));
        }
示例#7
0
        public void When_null_item_is_added_Then_its_key_exists()
        {
            var dict = new WeakValueDictionary <int, Item>();

            dict[1] = null;
            Item item;
            bool exists = dict.TryGetValue(1, out item);

            Assert.That(dict.Count, Is.EqualTo(1));
            Assert.That(exists, Is.True);
            Assert.That(item, Is.Null);
        }
        public void TryGetValue_ReferenceFound()
        {
            string k1 = "key";
            string v1 = "value";

            var dictionary = new WeakValueDictionary <string, string>();

            dictionary[k1] = v1;

            // Now look for the same key we inserted
            string v2;
            bool   result = dictionary.TryGetValue(k1, out v2);

            Assertion.AssertEquals(true, result);
            Assertion.AssertEquals(true, Object.ReferenceEquals(v1, v2));
        }
示例#9
0
        public async Task <BitmapSource> DownloadImageAsync(string url)
        {
            if (cache.TryGetValue(url, out var bitmapSource))
            {
                return(bitmapSource);
            }

            using (var webClient = new WebClient())
            {
                using (var ms = new MemoryStream(await webClient.DownloadDataTaskAsync(url).ConfigureAwait(false)))
                {
                    var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
                    bitmapSource = decoder.Frames[0];
                    bitmapSource.Freeze();
                    cache[url] = bitmapSource;
                    return(bitmapSource);
                }
            }
        }
        public void TryGetNullValue_ReferenceFound()
        {
            string k1 = "key";
            string v1 = null;

            var dictionary = new WeakValueDictionary <string, string>();

            dictionary[k1] = v1;

            // Now look for the same key we inserted
            string v2;
            bool   result = dictionary.TryGetValue(k1, out v2);

            Assertion.AssertEquals(true, result);
            Assertion.AssertEquals(true, Object.ReferenceEquals(v1, v2));

            // Should not scavenge values that are null, rather than collected
            dictionary.Scavenge();
            Assertion.AssertEquals(1, dictionary.Count);
        }
示例#11
0
        /// <summary>
        /// Discard any entries (weak and strong) which do not have the explicitlyLoaded flag set.
        /// </summary>
        internal void DiscardImplicitReferences()
        {
            lock (_locker)
            {
                // Make a new Weak cache only with items that have been explicitly loaded, this will be a small number, there will most likely
                // be many items which were not explicitly loaded (ie p2p references).
                WeakValueDictionary <string, ProjectRootElement> oldWeakCache = _weakCache;
                _weakCache = new WeakValueDictionary <string, ProjectRootElement>(StringComparer.OrdinalIgnoreCase);

                LinkedList <ProjectRootElement> oldStrongCache = _strongCache;
                _strongCache = new LinkedList <ProjectRootElement>();

                foreach (string projectPath in oldWeakCache.Keys)
                {
                    ProjectRootElement rootElement;

                    if (oldWeakCache.TryGetValue(projectPath, out rootElement))
                    {
                        if (rootElement.IsExplicitlyLoaded)
                        {
                            _weakCache[projectPath] = rootElement;
                        }

                        if (rootElement.IsExplicitlyLoaded && oldStrongCache.Contains(rootElement))
                        {
                            _strongCache.AddFirst(rootElement);
                        }
                        else
                        {
                            _strongCache.Remove(rootElement);
                            RaiseProjectRootElementRemovedFromStrongCache(rootElement);
                        }
                    }
                }
            }
        }
示例#12
0
        internal override ProjectRootElement Get(string projectFile, OpenProjectRootElement loadProjectRootElement, bool isExplicitlyLoaded,
                                                 bool?preserveFormatting)
        {
#if DEBUG
            // Verify that loadProjectRootElement delegate does not call ProjectRootElementCache.Get().
            s_getEntriesNumber++;
            ErrorUtilities.VerifyThrow(
                s_getEntriesNumber == 1,
                "Reentrance to the ProjectRootElementCache.Get function detected."
                );

            try {
#endif
            // Should already have been canonicalized
            ErrorUtilities.VerifyThrowInternalRooted(projectFile);

            ProjectRootElement projectRootElement;
            lock (_locker)
            {
                _weakCache.TryGetValue(projectFile, out projectRootElement);

                if (projectRootElement != null)
                {
                    BoostEntryInStrongCache(projectRootElement);

                    // An implicit load will never reset the explicit flag.
                    if (isExplicitlyLoaded)
                    {
                        projectRootElement.MarkAsExplicitlyLoaded();
                    }
                }
                else
                {
                    DebugTraceCache("Not found in cache: ", projectFile);
                }

                if (preserveFormatting != null && projectRootElement != null && projectRootElement.XmlDocument.PreserveWhitespace != preserveFormatting)
                {
                    // Cached project doesn't match preserveFormatting setting, so reload it
                    projectRootElement.Reload(true, preserveFormatting);
                }
            }

            bool projectRootElementIsInvalid = IsInvalidEntry(projectFile, projectRootElement);
            if (projectRootElementIsInvalid)
            {
                DebugTraceCache("Not satisfied from cache: ", projectFile);
                ForgetEntryIfExists(projectRootElement);
            }

            if (loadProjectRootElement == null)
            {
                if (projectRootElement == null || projectRootElementIsInvalid)
                {
                    return(null);
                }
                else
                {
                    DebugTraceCache("Satisfied from XML cache: ", projectFile);
                    return(projectRootElement);
                }
            }

            // Use openProjectRootElement to reload the element if the cache element does not exist or need to be reloaded.
            if (projectRootElement == null || projectRootElementIsInvalid)
            {
                // We do not lock loading with common _locker of the cache, to avoid lock contention.
                // Decided also not to lock this section with the key specific locker to avoid the overhead and code overcomplication, as
                // it is not likely that two threads would use Get function for the same project simultaneously and it is not a big deal if in some cases we load the same project twice.

                projectRootElement = loadProjectRootElement(projectFile, this);
                ErrorUtilities.VerifyThrowInternalNull(projectRootElement, "projectRootElement");
                ErrorUtilities.VerifyThrow(
                    projectRootElement.FullPath.Equals(projectFile, StringComparison.OrdinalIgnoreCase),
                    "Got project back with incorrect path. Expected path: {0}, received path: {1}.",
                    projectFile,
                    projectRootElement.FullPath
                    );

                // An implicit load will never reset the explicit flag.
                if (isExplicitlyLoaded)
                {
                    projectRootElement.MarkAsExplicitlyLoaded();
                }

                // Update cache element.
                // It is unlikely, but it might be that while without the lock, the projectRootElement in cache was updated by another thread.
                // And here its entry will be replaced with the loaded projectRootElement. This is fine:
                // if loaded projectRootElement is out of date (so, it changed since the time we loaded it), it will be updated the next time some thread calls Get function.
                AddEntry(projectRootElement);
            }
            else
            {
                DebugTraceCache("Satisfied from XML cache: ", projectFile);
            }


            return(projectRootElement);

#if DEBUG
        }

        finally
        {
            s_getEntriesNumber--;
        }
#endif
        }
        public void TryGetNullValue_ReferenceFound()
        {
            string k1 = "key";
            string v1 = null;

            var dictionary = new WeakValueDictionary<string, string>();
            dictionary[k1] = v1;

            // Now look for the same key we inserted
            string v2;
            bool result = dictionary.TryGetValue(k1, out v2);

            Assertion.AssertEquals(true, result);
            Assertion.AssertEquals(true, Object.ReferenceEquals(v1, v2));

            // Should not scavenge values that are null, rather than collected
            dictionary.Scavenge();
            Assertion.AssertEquals(1, dictionary.Count);
        }
        public void TryGetValue_ReferenceNotFound()
        {
            var dictionary = new WeakValueDictionary<string, string>();

            string v;
            bool result = dictionary.TryGetValue("x", out v);

            Assert.IsFalse(result);
            Assert.IsNull(v);
            Assert.IsFalse(dictionary.Contains("x"));
        }
        public void TryGetValue_ReferenceFound()
        {
            string k1 = "key";
            string v1 = "value";

            var dictionary = new WeakValueDictionary<string, string>();
            dictionary[k1] = v1;

            // Now look for the same key we inserted
            string v2;
            bool result = dictionary.TryGetValue(k1, out v2);

            Assertion.AssertEquals(true, result);
            Assertion.AssertEquals(true, Object.ReferenceEquals(v1, v2));
        }
示例#16
0
        public async Task <BitmapResult> GetBitmapAsync(string source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            // 检查内存缓存。
            BitmapImage bitmap;

            if (CacheBitmapImages.TryGetValue(source, out bitmap))
            {
                // 内存缓存存在,直接使用内存缓存。
                return(new BitmapResult(bitmap));
            }
            else
            {
                var uriSource = ToUriSource(source);
                if (IsHttpUri(uriSource))
                {
                    var cacheFilePath = GetCacheFilePath(uriSource);
                    if (File.Exists(cacheFilePath))
                    {
                        var bytes = await FileExtensions.ReadAllBytesAsync(cacheFilePath);

                        bitmap = new BitmapImage();
                        try
                        {
                            await bitmap.SetSourceAsync(new MemoryStream(bytes).AsRandomAccessStream());

                            // 放入内存缓存。
                            CacheBitmapImages[source] = bitmap;

                            return(new BitmapResult(bitmap));
                        }
                        catch (Exception ex)
                        {
                            // 缓存文件无法加载,删除缓存文件。
                            async void AsyncAction()
                            {
                                await Task.Run(() =>
                                {
                                    try
                                    {
                                        File.Delete(cacheFilePath);
                                    }
                                    catch (Exception)
                                    {
                                        // ignored
                                    }
                                });
                            }

                            AsyncAction();

                            return(new BitmapResult(ex));
                        }
                    }
                    else
                    {
                        Task <byte[]> imageDownloadTask;
                        if (!ImageDownloadTasks.TryGetValue(source, out imageDownloadTask))
                        {
                            imageDownloadTask          = DownloadImageAsync(uriSource);
                            ImageDownloadTasks[source] = imageDownloadTask;
                        }

                        byte[] bytes;
                        try
                        {
                            bytes = await imageDownloadTask;
                        }
                        catch (TaskCanceledException ex)
                        {
                            ImageDownloadTasks.TryRemove(source, out imageDownloadTask);
                            return(new BitmapResult(ex));
                        }
                        catch (HttpRequestException ex)
                        {
                            ImageDownloadTasks.TryRemove(source, out imageDownloadTask);
                            return(new BitmapResult(ex));
                        }

                        bitmap = new BitmapImage();
                        try
                        {
                            await bitmap.SetSourceAsync(new MemoryStream(bytes).AsRandomAccessStream());

                            // 放入内存缓存。
                            CacheBitmapImages[source] = bitmap;

                            async void AsyncAction()
                            {
                                try
                                {
                                    Directory.CreateDirectory(CacheFolderPath);
                                    await FileExtensions.WriteAllBytesAsync(cacheFilePath, bytes);
                                }
                                catch (Exception)
                                {
                                    // ignored
                                }
                                finally
                                {
                                    ImageDownloadTasks.TryRemove(source, out imageDownloadTask);
                                }
                            }
                            AsyncAction();

                            return(new BitmapResult(bitmap));
                        }
                        catch (Exception ex)
                        {
                            ImageDownloadTasks.TryRemove(source, out imageDownloadTask);
                            return(new BitmapResult(ex));
                        }
                    }
                }
                else
                {
                    byte[] bytes;
                    try
                    {
                        if (string.Equals(uriSource.Scheme, FileScheme, StringComparison.OrdinalIgnoreCase))
                        {
                            // 绝对路径。
                            bytes = await FileExtensions.ReadAllBytesAsync(source);
                        }
                        else
                        {
                            // ms-appx 或 ms-appdata,其它路径不支持。
                            var file = await StorageFile.GetFileFromApplicationUriAsync(uriSource);

                            var buffer = await FileIO.ReadBufferAsync(file);

                            bytes = buffer.ToArray();
                        }
                    }
                    catch (Exception ex)
                    {
                        return(new BitmapResult(ex));
                    }

                    bitmap = new BitmapImage();
                    try
                    {
                        await bitmap.SetSourceAsync(new MemoryStream(bytes).AsRandomAccessStream());

                        // 放入内存缓存。
                        CacheBitmapImages[source] = bitmap;

                        return(new BitmapResult(bitmap));
                    }
                    catch (Exception ex)
                    {
                        return(new BitmapResult(ex));
                    }
                }
            }
        }
示例#17
0
        /// <summary>
        /// Returns an existing ProjectRootElement for the specified file path, if any.
        /// If none exists, calls the provided delegate to load one, and adds that to the cache.
        /// The reason that it calls back to do this is so that the cache is locked between determining
        /// that the entry does not exist and adding the entry.
        ///
        /// If <see cref="_autoReloadFromDisk"/> was set to true, and the file on disk has changed since it was cached,
        /// it will be reloaded before being returned.
        ///
        /// Thread safe.
        /// </summary>
        /// <remarks>
        /// Never needs to consult the strong cache as well, since if the item is in there, it will
        /// not have left the weak cache.
        /// If item is found, boosts it to the top of the strong cache.
        /// </remarks>
        /// <param name="projectFile">The project file which contains the ProjectRootElement.  Must be a full path.</param>
        /// <param name="openProjectRootElement">The delegate to use to load if necessary. May be null.</param>
        /// <param name="isExplicitlyLoaded"><code>true</code> if the project is explicitly loaded, otherwise <code>false</code>.</param>
        /// <param name="preserveFormatting"><code>true</code> to the project was loaded with the formated preserved, otherwise <code>false</code>.</param>
        /// <returns>The ProjectRootElement instance if one exists.  Null otherwise.</returns>
        internal override ProjectRootElement Get(string projectFile, OpenProjectRootElement openProjectRootElement, bool isExplicitlyLoaded,
                                                 bool?preserveFormatting)
        {
            // Should already have been canonicalized
            ErrorUtilities.VerifyThrowInternalRooted(projectFile);

            lock (_locker)
            {
                ProjectRootElement projectRootElement;
                _weakCache.TryGetValue(projectFile, out projectRootElement);

                if (preserveFormatting != null && projectRootElement != null && projectRootElement.XmlDocument.PreserveWhitespace != preserveFormatting)
                {
                    //  Cached project doesn't match preserveFormatting setting, so reload it
                    projectRootElement.Reload(true, preserveFormatting);
                }

                if (projectRootElement != null && _autoReloadFromDisk)
                {
                    FileInfo fileInfo = FileUtilities.GetFileInfoNoThrow(projectFile);

                    // If the file doesn't exist on disk, go ahead and use the cached version.
                    // It's an in-memory project that hasn't been saved yet.
                    if (fileInfo != null)
                    {
                        bool forgetEntry = false;

                        if (fileInfo.LastWriteTime != projectRootElement.LastWriteTimeWhenRead)
                        {
                            // File was changed on disk by external means. Cached version is no longer reliable.
                            // We could throw here or ignore the problem, but it is a common and reasonable pattern to change a file
                            // externally and load a new project over it to see the new content. So we dump it from the cache
                            // to force a load from disk. There might then exist more than one ProjectRootElement with the same path,
                            // but clients ought not get themselves into such a state - and unless they save them to disk,
                            // it may not be a problem.
                            forgetEntry = true;
                        }
                        else if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDCACHECHECKFILECONTENT")))
                        {
                            // QA tests run too fast for the timestamp check to work. This environment variable is for their
                            // use: it checks the file content as well as the timestamp. That's better than completely disabling
                            // the cache as we get test coverage of the rest of the cache code.
                            XmlDocument document = new XmlDocument();
                            document.PreserveWhitespace = projectRootElement.XmlDocument.PreserveWhitespace;

                            using (var xtr = XmlReaderExtension.Create(projectRootElement.FullPath, projectRootElement.ProjectRootElementCache.LoadProjectsReadOnly))
                            {
                                document.Load(xtr.Reader);
                            }

                            string diskContent  = document.OuterXml;
                            string cacheContent = projectRootElement.XmlDocument.OuterXml;

                            if (diskContent != cacheContent)
                            {
                                forgetEntry = true;
                            }
                        }

                        if (forgetEntry)
                        {
                            ForgetEntry(projectRootElement);

                            DebugTraceCache("Out of date dropped from XML cache: ", projectFile);
                            projectRootElement = null;
                        }
                    }
                }

                if (projectRootElement == null && openProjectRootElement != null)
                {
                    projectRootElement = openProjectRootElement(projectFile, this);

                    ErrorUtilities.VerifyThrowInternalNull(projectRootElement, "projectRootElement");
                    ErrorUtilities.VerifyThrow(projectRootElement.FullPath == projectFile, "Got project back with incorrect path");
                    ErrorUtilities.VerifyThrow(_weakCache.Contains(projectFile), "Open should have renamed into cache and boosted");
                }
                else if (projectRootElement != null)
                {
                    DebugTraceCache("Satisfied from XML cache: ", projectFile);
                    BoostEntryInStrongCache(projectRootElement);
                }

                // An implicit load will never reset the explicit flag.
                if (projectRootElement != null && isExplicitlyLoaded)
                {
                    projectRootElement.MarkAsExplicitlyLoaded();
                }

                return(projectRootElement);
            }
        }
示例#18
0
        /// <summary>
        ///     Parse the given <paramref name="fileSpec" /> into a <see cref="MSBuildGlob" /> using a given
        ///     <paramref name="globRoot" />.
        /// </summary>
        /// <param name="globRoot">
        ///     The root of the glob.
        ///     The fixed directory part of the glob and the match arguments (<see cref="IsMatch" /> and <see cref="MatchInfo" />)
        ///     will get normalized against this root.
        ///     If empty, the current working directory is used.
        ///     Cannot be null, and cannot contain invalid path arguments.
        /// </param>
        /// <param name="fileSpec">The string to parse</param>
        /// <returns></returns>
        public static MSBuildGlob Parse(string globRoot, string fileSpec)
        {
            ErrorUtilities.VerifyThrowArgumentNull(globRoot, nameof(globRoot));
            ErrorUtilities.VerifyThrowArgumentNull(fileSpec, nameof(fileSpec));
            ErrorUtilities.VerifyThrowArgumentInvalidPath(globRoot, nameof(globRoot));

            if (string.IsNullOrEmpty(globRoot))
            {
                globRoot = Directory.GetCurrentDirectory();
            }

            globRoot = Strings.WeakIntern(FileUtilities.NormalizePath(globRoot).WithTrailingSlash());

            var lazyState = new Lazy <GlobState>(() =>
            {
                FileMatcher.Default.GetFileSpecInfo(
                    fileSpec,
                    out string fixedDirectoryPart,
                    out string wildcardDirectoryPart,
                    out string filenamePart,
                    out bool needsRecursion,
                    out bool isLegalFileSpec,
                    (fixedDirPart, wildcardDirPart, filePart) =>
                {
                    var normalizedFixedPart = NormalizeTheFixedDirectoryPartAgainstTheGlobRoot(fixedDirPart, globRoot);

                    return(normalizedFixedPart, wildcardDirPart, filePart);
                });

                Regex regex = null;
                if (isLegalFileSpec)
                {
                    string matchFileExpression = FileMatcher.RegularExpressionFromFileSpec(fixedDirectoryPart, wildcardDirectoryPart, filenamePart);

                    lock (s_regexCache)
                    {
                        s_regexCache.TryGetValue(matchFileExpression, out regex);
                    }

                    if (regex == null)
                    {
                        RegexOptions regexOptions = FileMatcher.DefaultRegexOptions;
                        // compile the regex since it's expected to be used multiple times
                        // For the kind of regexes used here, compilation on .NET Framework tends to be expensive and not worth the small
                        // run-time boost so it's enabled only on .NET Core by default.
#if RUNTIME_TYPE_NETCORE
                        bool compileRegex = true;
#else
                        bool compileRegex = !ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0);
#endif
                        if (compileRegex)
                        {
                            regexOptions |= RegexOptions.Compiled;
                        }
                        Regex newRegex = new Regex(matchFileExpression, regexOptions);
                        lock (s_regexCache)
                        {
                            if (!s_regexCache.TryGetValue(matchFileExpression, out regex))
                            {
                                s_regexCache[matchFileExpression] = newRegex;
                            }
                        }
                        regex ??= newRegex;
                    }
                }
                return(new GlobState(globRoot, fileSpec, isLegalFileSpec, fixedDirectoryPart, wildcardDirectoryPart, filenamePart, needsRecursion, regex));
            },
示例#19
0
        public async Task <BitmapResult> GetBitmapAsync(string source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            // 检查内存缓存。
            BitmapImage bitmap;

            if (CacheBitmapImages.TryGetValue(source, out bitmap))
            {
                // 内存缓存存在,直接使用内存缓存。
                return(new BitmapResult(bitmap));
            }
            else
            {
                var uriSource = ToUriSource(source);
                if (IsHttpUri(uriSource))
                {
                    var cacheFilePath = GetCacheFilePath(uriSource);
                    if (File.Exists(cacheFilePath))
                    {
                        await SemaphoreSlim.WaitAsync();

                        try
                        {
                            bitmap = new BitmapImage();
                            bitmap.BeginInit();
                            bitmap.UriSource = new Uri(cacheFilePath);
                            bitmap.EndInit();
                            // 放入内存缓存。
                            CacheBitmapImages[source] = bitmap;

                            return(new BitmapResult(bitmap));
                        }
                        catch (NotSupportedException ex)
                        {
                            // 缓存文件无法加载,删除缓存文件。
                            async void AsyncAction()
                            {
                                await Task.Run(() =>
                                {
                                    try
                                    {
                                        File.Delete(cacheFilePath);
                                    }
                                    catch (Exception)
                                    {
                                        // ignored
                                    }
                                });
                            }

                            AsyncAction();

                            return(new BitmapResult(ex));
                        }
                        finally
                        {
                            await Task.Delay(1);// 防止同时加载大量图片时,UI 线程卡死。

                            SemaphoreSlim.Release();
                        }
                    }
                    else
                    {
                        Task <byte[]> imageDownloadTask;
                        if (!ImageDownloadTasks.TryGetValue(source, out imageDownloadTask))
                        {
                            imageDownloadTask          = DownloadImageAsync(uriSource);
                            ImageDownloadTasks[source] = imageDownloadTask;
                        }

                        byte[] bytes;
                        try
                        {
                            bytes = await imageDownloadTask;
                        }
                        catch (HttpRequestException ex)
                        {
                            ImageDownloadTasks.TryRemove(source, out imageDownloadTask);
                            return(new BitmapResult(ex));
                        }

                        await SemaphoreSlim.WaitAsync();

                        try
                        {
                            bitmap = new BitmapImage();
                            bitmap.BeginInit();
                            bitmap.StreamSource = new MemoryStream(bytes);
                            bitmap.EndInit();
                            // 放入内存缓存。
                            CacheBitmapImages[source] = bitmap;

                            Action asyncAction = async() =>
                            {
                                try
                                {
                                    Directory.CreateDirectory(CacheFolderPath);
                                    await FileExtensions.WriteAllBytesAsync(cacheFilePath, bytes);
                                }
                                catch (Exception)
                                {
                                    // ignored
                                }
                                finally
                                {
                                    ImageDownloadTasks.TryRemove(source, out imageDownloadTask);
                                }
                            };
                            asyncAction.Invoke();

                            return(new BitmapResult(bitmap));
                        }
                        catch (NotSupportedException ex)
                        {
                            ImageDownloadTasks.TryRemove(source, out imageDownloadTask);
                            return(new BitmapResult(ex));
                        }
                        finally
                        {
                            await Task.Delay(1);// 防止同时加载大量图片时,UI 线程卡死。

                            SemaphoreSlim.Release();
                        }
                    }
                }
                else
                {
                    await SemaphoreSlim.WaitAsync();

                    try
                    {
                        bitmap = new BitmapImage();
                        bitmap.BeginInit();
                        bitmap.UriSource = uriSource;
                        bitmap.EndInit();
                        // 放入内存缓存。
                        CacheBitmapImages[source] = bitmap;

                        return(new BitmapResult(bitmap));
                    }
                    catch (FileNotFoundException ex)
                    {
                        return(new BitmapResult(ex));
                    }
                    catch (IOException ex)
                    {
                        return(new BitmapResult(ex));
                    }
                    catch (NotSupportedException ex)
                    {
                        return(new BitmapResult(ex));
                    }
                    finally
                    {
                        await Task.Delay(1);// 防止同时加载大量图片时,UI 线程卡死。

                        SemaphoreSlim.Release();
                    }
                }
            }
        }