控制台例子:
1. Nuget包管理器添加 StackExchange.Redis
2.代码如下:
using StackExchange.Redis;
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost,password=123456");
IDatabase db = redis.GetDatabase();
//redis键名
string resource = "myResourceName";
//锁的令牌
string lockToken = Guid.NewGuid().ToString();
//过期时间
TimeSpan expiry = TimeSpan.FromSeconds(5);
var tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
int client = (i + 1);
tasks[i] = Task.Run(async () =>
{
while (true)
{
//获得锁
if (db.LockTake(resource, lockToken, expiry))
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端{client} 创建了锁 ********************************* ");
//开启异步线程,定时2秒延长锁
var cancellationTokenSource = new CancellationTokenSource();
var extendLockTask = Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(2), cancellationTokenSource.Token);
bool extended = db.LockExtend(resource, lockToken, expiry);
if (extended)
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} --------------- 客户端{client} 已延长了锁 ---------------");
}
else
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}--------------- 客户端{client} 延长了锁失败!---------------");
break;
}
}
}, cancellationTokenSource.Token);
//模拟任务耗时
await Task.Delay(60);
//取消延长
cancellationTokenSource.Cancel();
try
{
await extendLockTask;
}
catch (OperationCanceledException)
{
//Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}--------------- 客户端{client} 延长任务取消!---------------");
}
//释放锁
db.LockRelease(resource, lockToken);
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端{client} 释放了锁 ********************************* ");
break;
}
else
{
//获取锁失败以后重试
//Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} 客户端{client}获取锁失败,正在重试...");
//await Task.Delay(50);
}
}
});
}
Task.WaitAll(tasks);
Task.WaitAll(tasks);
Console.WriteLine("按下回车键停止...");
Console.ReadLine();