redis cache invalidoperationexception:读取器完成后不允许读取

dl5txlt9  于 2021-06-09  发布在  Redis
关注(0)|答案(1)|浏览(519)

我有一个webjob,它不断地向redis插入数据,我有另一个时间触发函数,每5分钟从同一个redis缓存读取一次数据。

  1. public static void ProcessData([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
  2. {
  3. var newCacheclient = new RedisCacheClient(Program.spRedisCacheConnectionPoolMgr, Program.serializer, Program.redisConfiguration).Db0;
  4. var cachedData = newCacheclient.GetAsync<List<MyObject>>("mydata").Result;

在执行10-15分钟后,我从时间触发函数得到以下错误。有人知道如何解决这个问题吗?
invalidoperationexception:读取器完成后不允许读取。
我也向github提出了同样的问题。
nuget版本详细信息-

错误堆栈-内部异常1:

  1. InvalidOperationException: Reading is not allowed after reader was completed.
  2. at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
  3. at MyData.Functions.ExecuteTrade(TimerInfo myTimer) in C:\Users\\Functions.cs:line 27
  4. at Microsoft.Azure.WebJobs.Host.Executors.VoidMethodInvoker`1.InvokeAsync(TReflected instance, Object[] arguments)
  5. at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`1.<InvokeAsync>d__0.MoveNext()
  6. at System.IO.Pipelines.ThrowHelper.ThrowInvalidOperationException_NoReadingAllowed()
  7. at System.IO.Pipelines.Pipe.AdvanceReader(SequencePosition& consumed, SequencePosition& examined)
  8. at System.IO.Pipelines.Pipe.DefaultPipeReader.AdvanceTo(SequencePosition consumed, SequencePosition examined)
  9. at StackExchange.Redis.PhysicalConnection.<ReadFromPipe>d__110.MoveNext() in /_/src/StackExchange.Redis/PhysicalConnection.cs:line 1495
  10. at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  11. at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  12. at StackExchange.Redis.Extensions.Core.Implementations.RedisDatabase.<GetAsync>d__14`1.MoveNext()
vkc1a9a2

vkc1a9a21#

我看到代码中有几个问题:
您应该重用同一个redis客户端示例,以避免与redis服务器的tcp连接过多。
不要使用 .Result 以避免阻塞当前线程。将方法更新为异步并在getasync上使用await。
确保不要将大对象存储在缓存项中(在这种情况下 List<MyObject> 不应该是一个大的列表)
以下是更新的代码:

  1. private static readonly IRedisCacheClient redisCacheClient = new RedisCacheClient(Program.spRedisCacheConnectionPoolMgr, Program.serializer, Program.redisConfiguration);
  2. public static async Task ProcessData([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
  3. {
  4. var redisDB = redisCacheClient.Db0;
  5. var cachedData = await redisDB.GetAsync<List<MyObject>>("mydata").ConfigureAwait(false);
  6. }

相关问题