【问题标题】:How to use MemoryCache in C# Core Console app?如何在 C# Core Console 应用程序中使用 MemoryCache?
【发布时间】:2022-04-13 16:08:35
【问题描述】:

我想在 .NET Core 2.0 控制台应用程序中使用 Microsoft.Extensions.Caching.Memory.MemoryCache(实际上,在一个用于控制台或 asp.net 应用程序的库中)

我创建了一个测试应用:

using System;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var cache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions());

            int count = cache.Count;
            cache.CreateEntry("item1").Value = 1;
            int count2 = cache.Count;
            cache.TryGetValue("item1", out object item1);
            int count3 = cache.Count;
            cache.TryGetValue("item2", out object item2);
            int count4 = cache.Count;

            Console.WriteLine("Hello World!");
        }
    }
}

很遗憾,这不起作用。这些项目未添加到缓存中,并且无法检索。

我怀疑我需要使用 DependencyInjection,做这样的事情:

using System;
using Microsoft.Extensions.DependencyInjection;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var provider = new Microsoft.Extensions.DependencyInjection.ServiceCollection()
                .AddMemoryCache()
                .BuildServiceProvider();

            //And now?

            var cache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions());

            var xxx = PSP.Helpers.DependencyInjection.ServiceProvider;
            int count = cache.Count;
            cache.CreateEntry("item1").Value = 1;
            int count2 = cache.Count;
            cache.TryGetValue("item1", out object item1);
            int count3 = cache.Count;
            cache.TryGetValue("item2", out object item2);
            int count4 = cache.Count;

            Console.WriteLine("Hello World!");
        }
    }
}

不幸的是,这也不起作用,我怀疑我不应该创建新的内存缓存,而是从服务提供商那里获取它,但一直无法做到。

有什么想法吗?

【问题讨论】:

    标签: c# .net-core console-application


    【解决方案1】:

    配置提供程序后,通过GetService 扩展方法检索缓存

    var provider = new ServiceCollection()
                           .AddMemoryCache()
                           .BuildServiceProvider();
    
    //And now?
    var cache = provider.GetService<IMemoryCache>();
    
    //...other code removed for brevity;
    

    来自 cmets:

    不需要使用依赖注入,唯一需要的就是处理 CreateEntry() 的返回值。 CreateEntry 返回的条目需要被释放。上 dispose,它被添加到缓存中:

    using (var entry = cache.CreateEntry("item2")) { 
        entry.Value = 2; 
        entry.AbsoluteExpiration = DateTime.UtcNow.AddDays(1); 
    }
    

    【讨论】:

    • @remcolam 我建议在这里检查文档以确保您正确使用它docs.microsoft.com/en-us/aspnet/core/performance/caching/…
    • 啊,我缺少的组件是:当 CreateEntry 返回的条目需要被释放时。处置时将其添加到缓存中: using (var entry = cache.CreateEntry("item2")) { entry.Value = 2; entry.AbsoluteExpiration = DateTime.UtcNow.AddDays(1); }
    • PS:不需要依赖注入,只需要处理CreateEntry()的返回值
    • @remcolam 会将您的发现添加到答案中,以便对其他人有用。
    • 您好!是否可以在本地保存此内存缓存,以便在应用程序执行之间可以检索它?每次我重新启动控制台应用程序时,缓存都消失了:(
    【解决方案2】:
    IMemoryCache cache = new MemoryCache(new MemoryCacheOptions());
    object result = cache.Set("Key", new object());
    bool found = cache.TryGetValue("Key", out result);
    

    在 GitHub 中查看完整的 Memory Cache Sample

    您需要在项目中添加 NuGet Microsoft.Extensions.Caching.Memory 包以供使用 MemoryCache

    【讨论】:

      【解决方案3】:

      这是 .NET Core 中完整的控制台应用程序代码

      using Microsoft.Extensions.Caching.Memory;
      using Microsoft.Extensions.Primitives;
      using System;
      
      using System.Threading;
      
      namespace InMemoryNetCore
      {
         class Program
        {
            static void Main(string[] args)
           {
              IMemoryCache cache = new MemoryCache(new MemoryCacheOptions());
              object result;
              string key = "KeyName";
        
      
              // Create / Overwrite
              result = cache.Set(key, "Testing 1");
              result = cache.Set(key, "Update 1");
      
              // Retrieve, null if not found
              result = cache.Get(key);
              Console.WriteLine("Output of KeyName Value="+result);
      
              // Check if Exists
              bool found = cache.TryGetValue(key, out result);
      
              Console.WriteLine("KeyName Found=" + result);
      
              // Delete item
              cache.Remove(key);
      
      
              //set item with token expiration and callback
              TimeSpan expirationMinutes = System.TimeSpan.FromSeconds(0.1);
              var expirationTime = DateTime.Now.Add(expirationMinutes);
              var expirationToken = new CancellationChangeToken(
                  new CancellationTokenSource(TimeSpan.FromMinutes(0.001)).Token);
      
              // Create cache item which executes call back function
              var cacheEntryOptions = new MemoryCacheEntryOptions()
             // Pin to cache.
             .SetPriority(Microsoft.Extensions.Caching.Memory.CacheItemPriority.Normal)
             // Set the actual expiration time
             .SetAbsoluteExpiration(expirationTime)
             // Force eviction to run
             .AddExpirationToken(expirationToken)
             // Add eviction callback
             .RegisterPostEvictionCallback(callback: CacheItemRemoved);
              //add cache Item with options of callback
              result = cache.Set(key,"Call back cache Item", cacheEntryOptions);
      
      
              Console.WriteLine(result);
      
      
      
              Console.ReadKey();
      
          }
      
          private static void CacheItemRemoved(object key, object value, EvictionReason reason, object state)
          {
              Console.WriteLine(key + " " + value + " removed from cache due to:" + reason);
            }
         }
      }
      

      来源:In Memory cache C# (Explanation with example in .NET and .NET Core)

      【讨论】:

        【解决方案4】:

        对于上面的回复,我想为常见的缓存操作添加一些简洁的替代方案:

        using Microsoft.Extensions.Caching.Memory;
        
        // ... (further down) ...
        MemoryCache cache = new MemoryCache(new MemoryCacheOptions() );
        
        // get a value from the cache
        // both are equivalent
        // obviously, replace "string" with the correct type
        string value = (string)cache.Get("mykey");
        string value = cache.Get<string>("mykey");
        
        // setting values in the cache
        // no expiration time
        cache.Set("mykey", myVar);
        
        // absolute expiration numMinutes from now
        cache.Set("mykey", myVar, DateTimeOffset.Now.AddMinutes(numMinutes));
        
        // sliding expiration numMinutes from now
        // "sliding expiration" means that if it's accessed within the time period,
        //      the expiration is extended
        MemoryCacheEntryOptions options = new MemoryCacheEntryOptions();
        options.SetSlidingExpiration(TimeSpan.FromMinutes(numMinutes));
        webcache.Set("mykey", myVar, options);
        
        // or, if you want to do it all in one statement:
        webcache.Set("mykey", myVar, 
            new MemoryCacheEntryOptions {SlidingExpiration = TimeSpan.FromMinutes(numMinutes)});
        
        

        【讨论】:

          【解决方案5】:

          在 Asp 网络核心控制器的 AutomaticTest 上下文中,我在测试准备设置中分配了一个 MemoryCache 实例,如下所示:

              TestCaseController _sut;
              long? NO_SIZE_LIMIT = null;
          
              [SetUp]
              public void Setup()
              {
                  var options = new MemoryCacheOptions() 
                  { 
                      Clock = new SystemClock(), 
                      CompactionPercentage = 1, 
                      ExpirationScanFrequency = TimeSpan.FromSeconds(100), 
                      SizeLimit = NO_SIZE_LIMIT
                  };
                  IOptions<MemoryCacheOptions> optionsAccessor = Options.Create(options);
                  IMemoryCache memoryCache= new MemoryCache(optionsAccessor);
                  _sut = new TestCaseController(memoryCache);
              }
          

          目标控制器然后像这样使用缓存:

              [HttpGet("Active")]
              public IEnumerable<TestCase> GetActive()
              {
                  LogRequest();
                  IEnumerable<TestCase> ret;
                  var cacheKey = "TestCaseActive";
                  if (!_memoryCache.TryGetValue(cacheKey, out ret))
                  {
                      ret = _dbRepo.GetActive();
                      var cacheExpiryOptions = new MemoryCacheEntryOptions
                      {
                          AbsoluteExpiration = DateTime.Now.AddSeconds(60),
                          Priority = CacheItemPriority.High,
                          SlidingExpiration = TimeSpan.FromSeconds(50)
                      };
                      _memoryCache.Set(cacheKey, ret, cacheExpiryOptions);
                  }
                  else
                  {
                      _log.Debug("Fetch Cache");
                  }
                  _log.Debug(ret.Count() + " items returned");
                  return ret;
              }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-07-05
            • 1970-01-01
            • 1970-01-01
            • 2016-07-21
            • 2017-09-26
            相关资源
            最近更新 更多