Skip to content

常用的操作有同步锁和异步锁,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}}