スレッド環境で実行しているときにredisに問題があります。スレッド環境でのRedisが矛盾しています
私はAwaitableParallelForeachWorkerというクラスを持っています。このクラスでは、ペイロード内の各アイテムに対して特定の関数を実行できます。私は私のRedisのキャッシュAwaitableParallelForeachWorker
を使用して1000倍を呼び出して、この簡単なテストを書かれているpublic class NewsappRedisCache : INewsappRedisCache
{
private static readonly string ConnectionString = ConfigurationManager.AppSettings["RedisCache"];
private static readonly Lazy<ConnectionMultiplexer> LazyConnection =
new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(ConnectionString));
private static IDatabase MimerArticleDatabase => Connection.GetDatabase(2);
public async Task<MimerArticle> GetMimerArticleAsync(Guid id)
{
var redisValue = await MimerArticleDatabase.StringGetAsync($"{nameof(MimerArticle)}-{id}");
if (!redisValue.HasValue) return null;
var mimerArticle = JsonConvert.DeserializeObject<MimerArticle>(redisValue.ToString());
return mimerArticle;
}
:ここ
public class AwaitableParallelForeachWorker : IAwaitableParallelForeachWorker
{
private readonly object _lockObject = new object();
private int _tasksCompleted;
public async Task Run<T>(Func<T, Task> action, IEnumerable<T> payload)
{
var list = payload.ToList();
var tasks = list.Select(x => new Task(async() =>
{
await action(x);
TaskDone();
}));
Parallel.ForEach(tasks, task => task.Start());
while (_tasksCompleted < list.Count)
{
await Task.Delay(10);
}
}
public void TaskDone()
{
lock (_lockObject)
{
_tasksCompleted++;
}
}
}
はRedisのキャッシュコードだ(私はそれはきれいではありません知っているが、それは仕事をしていません)
public class Test
{
private NewsappRedisCache _redisCache;
[Fact]
public async void TestRedis()
{
var guids = new List<Guid>();
for (var i = 0; i < 1000; i++)
{
guids.Add(Guid.NewGuid());
}
_redisCache = new NewsappRedisCache();
await new AwaitableParallelForeachWorker().Run(CallRedis, guids);
}
private async Task CallRedis(Guid id)
{
await _redisCache.GetMimerArticleAsync(id);
}
}
今は変です。時には、redisキャッシュへの1000回の取得が分割されて実行されることもあります。私はazureポータルをチェックして実際にキャッシュにヒットしたことを確認しました。しかし、時にはそれぞれの取得に約1秒かかります。
私には理由が分かりません。私はAwaitableParallelForeachWorkerの機能を変更しようとしましたが、矛盾しています。 もし私がそれぞれ通常のforeachを実行すると、AwaitableParallelForeachWorkerが実際に動作したときと同じくらい速く実行されます。
私はそれがスレッド/タスクと関係があると思って立ち往生しています。
助けてもらえますか?
私は正確な理由を見つけることができませんが、私は考慮すべきいくつかのものですので、ここで、いずれかのコメントでこれをフィットすることはできません
Task.WhenAll(payload.Select(アクション))への変更は、トリックをしました! 私はこれまで、以下を使用していました:return Task.WhenAll(payload.Select(async x => await action(x)))、それは私が作った奇妙なRunメソッドと同じでした。だからこそ私はRunをそのように実装したのです...私は明らかに非同期ではなく、まだまだ待っています。 Anwyaysは本当にありがとう! – Boenne