相关疑难解决方法(0)

锁定模式以正确使用.NET MemoryCache

我假设此代码存在并发问题:

const string CacheKey = "CacheKey";
static string GetCachedData()
{
    string expensiveString =null;
    if (MemoryCache.Default.Contains(CacheKey))
    {
        expensiveString = MemoryCache.Default[CacheKey] as string;
    }
    else
    {
        CacheItemPolicy cip = new CacheItemPolicy()
        {
            AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddMinutes(20))
        };
        expensiveString = SomeHeavyAndExpensiveCalculation();
        MemoryCache.Default.Set(CacheKey, expensiveString, cip);
    }
    return expensiveString;
}
Run Code Online (Sandbox Code Playgroud)

并发问题的原因是多个线程可以获取空键,然后尝试将数据插入缓存.

什么是最简洁,最干净的方法来使这个代码并发证明?我喜欢在缓存相关代码中遵循一个好的模式.链接到在线文章将是一个很大的帮助.

更新:

我根据@Scott Chamberlain的回答提出了这个代码.任何人都可以找到任何性能或并发问题吗?如果这样做,它将节省许多代码和错误.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Caching;

namespace CachePoc
{
    class Program
    {
        static object everoneUseThisLockObject4CacheXYZ = new object();
        const string CacheXYZ = "CacheXYZ";
        static …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading memorycache

110
推荐指数
4
解决办法
9万
查看次数

缓存属性vs Lazy <T>

在.NET 4中,还可以使用System.Lazy<T>该类编写具有缓存属性的以下代码段.我测量了两种方法的性能,它几乎是一样的.对于为什么我应该使用一个而不是另一个,是否有任何真正的好处或魔力?

缓存属性

public static class Brushes
{
    private static LinearGradientBrush _myBrush;

    public static LinearGradientBrush MyBrush
    {
        get
        {
            if (_myBrush == null)
            {
                var linearGradientBrush = new LinearGradientBrush { ...};
                linearGradientBrush.GradientStops.Add( ... );
                linearGradientBrush.GradientStops.Add( ... );

                _myBrush = linearGradientBrush;
            }

            return _myBrush;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

懒惰<T>

public static class Brushes
{
    private static readonly Lazy<LinearGradientBrush> _myBrush =
        new Lazy<LinearGradientBrush>(() =>
            {
                var linearGradientBrush = new LinearGradientBrush { ...};
                linearGradientBrush.GradientStops.Add( ... );
                linearGradientBrush.GradientStops.Add( ... );

                return linearGradientBrush;
            } …
Run Code Online (Sandbox Code Playgroud)

.net c# lazy-loading .net-4.0

50
推荐指数
2
解决办法
8088
查看次数

Lazy <T>的缺点?

我最近在整个应用程序中开始使用Lazy,我想知道在使用时是否有任何明显的消极方面需要考虑Lazy<T>

我试图Lazy<T>尽可能经常使用,主要是为了帮助减少加载但非活动插件的内存占用.

c# mef lazy-evaluation

48
推荐指数
4
解决办法
4898
查看次数

Lazy <T>无异常缓存

是否System.Lazy<T>有无例外的缓存?或者懒惰的多线程初始化和缓存的另一个很好的解决方案?

我有以下程序(在这里小提琴):

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using System.Net;

namespace ConsoleApplication3
{
    public class Program
    {
        public class LightsaberProvider
        {
            private static int _firstTime = 1;

            public LightsaberProvider()
            {
                Console.WriteLine("LightsaberProvider ctor");
            }

            public string GetFor(string jedi)
            {
                Console.WriteLine("LightsaberProvider.GetFor jedi: {0}", jedi);

                Thread.Sleep(TimeSpan.FromSeconds(1));
                if (jedi == "2" && 1 == Interlocked.Exchange(ref _firstTime, 0))
                {
                    throw new Exception("Dark side happened...");
                }

                Thread.Sleep(TimeSpan.FromSeconds(1));
                return string.Format("Lightsaver for: {0}", jedi);
            }
        }

        public class LightsabersCache
        {
            private readonly …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading caching lazy-evaluation

9
推荐指数
4
解决办法
2191
查看次数

在 MemoryCache 调用上停止重入

应用程序需要加载数据并缓存一段时间。我希望如果应用程序的多个部分想要同时访问同一个缓存键,缓存应该足够智能,只加载一次数据并将该调用的结果返回给所有调用者。然而,MemoryCache并不是这样做的。如果您并行访问缓存(这通常发生在应用程序中),它会为每次尝试获取缓存值创建一个任务。我认为这段代码会达到预期的结果,但事实并非如此。我希望缓存只运行一项GetDataAsync任务,等待它完成,然后使用结果来获取其他调用的值。

using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ConsoleApp4
{
    class Program
    {
        private const string Key = "1";
        private static int number = 0;

        static async Task Main(string[] args)
        {
            var memoryCache = new MemoryCache(new MemoryCacheOptions { });

            var tasks = new List<Task>();
            tasks.Add(memoryCache.GetOrCreateAsync(Key, (cacheEntry) => GetDataAsync()));
            tasks.Add(memoryCache.GetOrCreateAsync(Key, (cacheEntry) => GetDataAsync()));
            tasks.Add(memoryCache.GetOrCreateAsync(Key, (cacheEntry) => GetDataAsync()));

            await Task.WhenAll(tasks);

            Console.WriteLine($"The cached value was: {memoryCache.Get(Key)}");
        }

        public static async Task<int> GetDataAsync()
        {
            //Simulate getting a large …
Run Code Online (Sandbox Code Playgroud)

.net c# concurrency memorycache concurrentdictionary

6
推荐指数
1
解决办法
431
查看次数

为什么使用Lazy <T>而不是静态工厂类用于单身?

在找到Lazy<T>类型之前,我使用以下模式来实现全局单例:

class DataModel
{
    public static XmlSerializer Serializer
    {
        get { return SerializerFactory.instance; }
    }

    static class SerializerFactory
    {
        internal static readonly XmlSerializer instance =
            new XmlSerializer(typeof(DataModel));
    }    
}
Run Code Online (Sandbox Code Playgroud)

此模式具有以下优点:

  1. 类型初始化是懒惰的.
  2. 类型初始化是线程安全的.
  3. 单例访问只是一个没有方法调用的直接字段访问.

最近我发现了很多帖子,建议Lazy<T>实现类似的单例访问模式.Lazy<T>(或LazyInitializer)是否会为此实施带来任何好处?

c# singleton

5
推荐指数
1
解决办法
915
查看次数

可能是双重双锁检查的错误实现

我在项目代码中找到了以下双锁检查实现:

  public class SomeComponent
  {
    private readonly object mutex = new object();

    public SomeComponent()
    {
    }

    public bool IsInitialized { get; private set; }

    public void Initialize()
    {
        this.InitializeIfRequired();
    }

    protected virtual void InitializeIfRequired()
    {
        if (!this.OnRequiresInitialization())
        {
            return;
        }

        lock (this.mutex)
        {
            if (!this.OnRequiresInitialization())
            {
                return;
            }

            try
            {
                this.OnInitialize();
            }
            catch (Exception)
            {
                throw;
            }

            this.IsInitialized = true;
        }
    }

    protected virtual void OnInitialize()
    {
        //some code here
    }

    protected virtual bool OnRequiresInitialization()
    {
        return !this.IsInitialized;
    }
} …
Run Code Online (Sandbox Code Playgroud)

c# concurrency locking

1
推荐指数
1
解决办法
253
查看次数