常用的操作有同步锁和异步锁,RsCode中使用如下:
确保同一时间只有一个线程可以执行lock块内的代码。
同步锁
csharp
using ( new AsyncLock().Lock())
{
//protected code
}
异步锁
专为异步操作设计的锁,可以安全地在async/await上下文中使用,避免了阻塞线程。
csharp
AsyncLock m=new AsyncLock();
using (await m.LockAsync())
{
//protected code
}
AsyncLock 第一个参数:初始任务数,第二个参数:最多任务数,默认值都为1
使用第三方库 Nito.AsyncEx
进行异步锁
csharp
using Nito.AsyncEx;
public async Task test()
{
AsyncLock _mutex = new AsyncLock();
using (await _mutex.LockAsync())
{
//async ...
}
}
限制线程访问数量
控制多线程对指定资源的访问,它的构造函数SemaphoreSlim(int initialCount)用于设置线程的数量,Wait()方法用于阻塞其中多余数量(例如代码中的3个线程)的线程,当线程数量在允许的范围内时此线程可以进入指定的代码,否则不能进入;Release()方法用于当线程执行完后释放资源,释放后下一个线程则可以进入此部分的代码;
csharp
SemaphoreSlim semaphoreSlim=new SemaphoreSlim(3);
try
{
semaphoreSlim.Wait();
}
finally
{
semaphoreSlim.Release();
}
跨线程共享对象
多线程中实现跨线程共享对象,在RsCode中调用ObjectContext<T>
实现
示例代码,在不同的线程中访问BrowserInfo对象,对比结果
csharp
//AService和BService分别访问线程上下文对象BrowserInfo ,对比两个不同线程操作结果
public class AService
{
public Task Add()
{
Console.WriteLine("AService1" + JsonSerializer.Serialize(ObjectContext<BrowserInfo>.Current));
ObjectContext<BrowserInfo>.Current.BrowserId = "aaaaaaa";
Console.WriteLine("AService2" + JsonSerializer.Serialize(ObjectContext<BrowserInfo>.Current));
return Task.CompletedTask;
}
}
public class BService
{
public Task Add()
{
Console.WriteLine("BService1" + JsonSerializer.Serialize(ObjectContext<BrowserInfo>.Current));
ObjectContext<BrowserInfo>.Current.BrowserId = "bbbbbbbbbbb";
Console.WriteLine("BService2" + JsonSerializer.Serialize(ObjectContext<BrowserInfo>.Current));
return Task.CompletedTask;
}
}
await Task.Run(async () =>
{
BrowserInfo browserInfo = new BrowserInfo()
{
BrowserId = "1111111111111"
};
ObjectContext<BrowserInfo> context = new ObjectContext<BrowserInfo>(browserInfo);
Console.WriteLine("start1 " + JsonSerializer.Serialize(context));
await new AService().Add();
await new BService().Add();
Console.WriteLine("end1 " + JsonSerializer.Serialize(context));
});
await Task.Run(async () =>
{
BrowserInfo browserInfo = new BrowserInfo()
{
BrowserId = "222222222222"
};
ObjectContext<BrowserInfo> context = new ObjectContext<BrowserInfo>(browserInfo);
Console.WriteLine("start2 " + JsonSerializer.Serialize(context));
await new AService().Add();
await new BService().Add();
Console.WriteLine("end2 " + JsonSerializer.Serialize(context));
});
响应结果
cmd
start1 {"Instance":{"BrowserId":"1111111111111","Status":false}}
AService1{"BrowserId":"1111111111111","Status":false}
AService2{"BrowserId":"aaaaaaa","Status":false}
BService1{"BrowserId":"aaaaaaa","Status":false}
BService2{"BrowserId":"bbbbbbbbbbb","Status":false}
end1 {"Instance":{"BrowserId":"bbbbbbbbbbb","Status":false}}
start2 {"Instance":{"BrowserId":"222222222222","Status":false}}
AService1{"BrowserId":"222222222222","Status":false}
AService2{"BrowserId":"aaaaaaa","Status":false}
BService1{"BrowserId":"aaaaaaa","Status":false}
BService2{"BrowserId":"bbbbbbbbbbb","Status":false}
end2 {"Instance":{"BrowserId":"bbbbbbbbbbb","Status":false}}