async Lazy<T> 立即得到结果
async Lazy<T> getting results right away
我有以下内容:
public class User
{
private readonly Lazy<Task<List<ReminderDb>>> _reminders;
public SmsUserDb()
{
// Get _reminderReader from IoC
_reminders = new Lazy<Task<List<ReminderDb>>>(async () => (List<ReminderDb>)await _reminderReader.Get(UserId));
}
public string UserId { get; set; }
public Task<List<ReminderDb>> Reminders => _reminders.Value;
}
当我像这样实例化一个对象时:
var n = new SmsUserDb {UserId = "123456"};
var rems = await n.Reminders;
此代码有效,我看到 n.Reminders ="Waiting for activation" 直到我点击 await n.Reminders 行。
但是,当我像这样从缓存中查询这个用户对象时:
var n1 = await _userReader.GetUserFromCache("+17084556675"); // return SmsUserDb
var n2 = await n1.Reminders;
当它点击 GetUserFromCache() 时,它会立即调用 _reminderReader.Get(UserId),它会再次调用缓存以获取提醒。然后它就超时了。所以 Lazy 不起作用,很可能会导致死锁。
public async Task<SmsUserDb> GetUserFromCache(string phoneNumber)
{
var hash = CachedObjectType.smsuser.ToString();
var fieldKey = string.Format($"{CachedObjectType.smsuser.ToString()}:user-{phoneNumber}");
var result = await _cacheUserService.GetHashedAsync(hash, fieldKey);
return result;
}
private async Task<List<ReminderDb>> GetRemindersFromCache(string userId)
{
var hash = CachedObjectType.smsreminder.ToString();
var fieldKey = string.Format($"{CachedObjectType.smsreminder.ToString()}:user-{userId}");
var result = await _cacheService.GetHashedAsync(hash, fieldKey);
return result ?? new List<ReminderDb>();
}
可能是什么问题?
这在我的测试代码中一切正常(如下所示)。因此,错误一定是在您未向我们展示的某些代码中。
这是一些有效的示例代码 - 它证明 Lazy<T>
工作正常。因此错误在您的代码中的其他地方。
您必须 post 一个可编译的复制品以便任何人都能帮助您。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Demo
{
public class ReminderDb
{
public string Value;
}
public class ReminderReader
{
public async Task<List<ReminderDb>> Get(string userId)
{
Console.WriteLine("In Get() for " + userId);
await Task.Delay(1000);
Console.WriteLine("Returning from Get()");
return new List<ReminderDb>{new ReminderDb{Value = userId}};
}
}
public class Cache
{
public void Add(string key, SmsUserDb value)
{
_cache.Add(key, value);
}
public async Task<SmsUserDb> GetHashedAsync(string key)
{
await Task.Delay(1000);
return _cache[key];
}
readonly Dictionary<string, SmsUserDb> _cache = new Dictionary<string, SmsUserDb>();
}
public class SmsUserDb
{
readonly Lazy<Task<List<ReminderDb>>> _reminders;
readonly ReminderReader _reminderReader = new ReminderReader();
public SmsUserDb()
{
_reminders = new Lazy<Task<List<ReminderDb>>>(async () => (List<ReminderDb>) await _reminderReader.Get(UserId));
}
public string UserId { get; set; }
public Task<List<ReminderDb>> Reminders => _reminders.Value;
}
static class Program
{
static async Task Main()
{
var db = new SmsUserDb(){UserId = "user ID"};
var cache = new Cache();
cache.Add("key", db);
Console.WriteLine("Press RETURN to await cache.GetHashedAsync()");
Console.ReadLine();
var result = await cache.GetHashedAsync("key");
Console.WriteLine("Press RETURN to await Reminders[0].Value");
Console.ReadLine();
Console.WriteLine((await result.Reminders)[0].Value);
}
}
}
找到问题了。我使用相同的 class 写入缓存,即:
public class User
{
private readonly Lazy<Task<List<ReminderDb>>> _reminders;
public SmsUserDb()
{
// Get _reminderReader from IoC
_reminders = new Lazy<Task<List<ReminderDb>>>(async () => (List<ReminderDb>)await _reminderReader.Get(UserId));
}
public string UserId { get; set; }
public Task<List<ReminderDb>> Reminders => _reminders.Value;
}
在使用不同的 class 进行书写(下方)和阅读(上方)后,一切正常。谢谢
public class CacheUser {
public string UserId { get; set; }
public List<ReminderDb> Reminders {get; set; }
}
我有以下内容:
public class User
{
private readonly Lazy<Task<List<ReminderDb>>> _reminders;
public SmsUserDb()
{
// Get _reminderReader from IoC
_reminders = new Lazy<Task<List<ReminderDb>>>(async () => (List<ReminderDb>)await _reminderReader.Get(UserId));
}
public string UserId { get; set; }
public Task<List<ReminderDb>> Reminders => _reminders.Value;
}
当我像这样实例化一个对象时:
var n = new SmsUserDb {UserId = "123456"};
var rems = await n.Reminders;
此代码有效,我看到 n.Reminders ="Waiting for activation" 直到我点击 await n.Reminders 行。
但是,当我像这样从缓存中查询这个用户对象时:
var n1 = await _userReader.GetUserFromCache("+17084556675"); // return SmsUserDb
var n2 = await n1.Reminders;
当它点击 GetUserFromCache() 时,它会立即调用 _reminderReader.Get(UserId),它会再次调用缓存以获取提醒。然后它就超时了。所以 Lazy 不起作用,很可能会导致死锁。
public async Task<SmsUserDb> GetUserFromCache(string phoneNumber)
{
var hash = CachedObjectType.smsuser.ToString();
var fieldKey = string.Format($"{CachedObjectType.smsuser.ToString()}:user-{phoneNumber}");
var result = await _cacheUserService.GetHashedAsync(hash, fieldKey);
return result;
}
private async Task<List<ReminderDb>> GetRemindersFromCache(string userId)
{
var hash = CachedObjectType.smsreminder.ToString();
var fieldKey = string.Format($"{CachedObjectType.smsreminder.ToString()}:user-{userId}");
var result = await _cacheService.GetHashedAsync(hash, fieldKey);
return result ?? new List<ReminderDb>();
}
可能是什么问题?
这在我的测试代码中一切正常(如下所示)。因此,错误一定是在您未向我们展示的某些代码中。
这是一些有效的示例代码 - 它证明 Lazy<T>
工作正常。因此错误在您的代码中的其他地方。
您必须 post 一个可编译的复制品以便任何人都能帮助您。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Demo
{
public class ReminderDb
{
public string Value;
}
public class ReminderReader
{
public async Task<List<ReminderDb>> Get(string userId)
{
Console.WriteLine("In Get() for " + userId);
await Task.Delay(1000);
Console.WriteLine("Returning from Get()");
return new List<ReminderDb>{new ReminderDb{Value = userId}};
}
}
public class Cache
{
public void Add(string key, SmsUserDb value)
{
_cache.Add(key, value);
}
public async Task<SmsUserDb> GetHashedAsync(string key)
{
await Task.Delay(1000);
return _cache[key];
}
readonly Dictionary<string, SmsUserDb> _cache = new Dictionary<string, SmsUserDb>();
}
public class SmsUserDb
{
readonly Lazy<Task<List<ReminderDb>>> _reminders;
readonly ReminderReader _reminderReader = new ReminderReader();
public SmsUserDb()
{
_reminders = new Lazy<Task<List<ReminderDb>>>(async () => (List<ReminderDb>) await _reminderReader.Get(UserId));
}
public string UserId { get; set; }
public Task<List<ReminderDb>> Reminders => _reminders.Value;
}
static class Program
{
static async Task Main()
{
var db = new SmsUserDb(){UserId = "user ID"};
var cache = new Cache();
cache.Add("key", db);
Console.WriteLine("Press RETURN to await cache.GetHashedAsync()");
Console.ReadLine();
var result = await cache.GetHashedAsync("key");
Console.WriteLine("Press RETURN to await Reminders[0].Value");
Console.ReadLine();
Console.WriteLine((await result.Reminders)[0].Value);
}
}
}
找到问题了。我使用相同的 class 写入缓存,即:
public class User
{
private readonly Lazy<Task<List<ReminderDb>>> _reminders;
public SmsUserDb()
{
// Get _reminderReader from IoC
_reminders = new Lazy<Task<List<ReminderDb>>>(async () => (List<ReminderDb>)await _reminderReader.Get(UserId));
}
public string UserId { get; set; }
public Task<List<ReminderDb>> Reminders => _reminders.Value;
}
在使用不同的 class 进行书写(下方)和阅读(上方)后,一切正常。谢谢
public class CacheUser {
public string UserId { get; set; }
public List<ReminderDb> Reminders {get; set; }
}