为了账号安全,请及时绑定邮箱和手机立即绑定

SemaphoreSlim 类中的 WaitHandle.WaitOne() 方法无法正常工作

SemaphoreSlim 类中的 WaitHandle.WaitOne() 方法无法正常工作

C#
守着一只汪 2021-11-21 18:03:08
我有一个复杂的情况,但我会尽量缩短它,只知道重要的细节。我正在尝试实现基于任务的作业处理。这是课程:internal class TaskBasedJob : IJob{    public WaitHandle WaitHandle { get; }    public JobStatus Status { get; private set; }    public TaskBasedJob(Func<Task<JobStatus>> action, TimeSpan interval, TimeSpan delay)    {         Status = JobStatus.NotExecuted;        var semaphore = new SemaphoreSlim(0, 1);        WaitHandle = semaphore.AvailableWaitHandle;        _timer = new Timer(async x =>        {            // return to prevent duplicate executions            // Semaphore starts locked so WaitHandle works properly            if (semaphore.CurrentCount == 0 && Status != JobStatus.NotExecuted)            {                return;                Status = JobStatus.Failure;            }            if(Status != JobStatus.NotExecuted)                await semaphore.WaitAsync();            try            {                await action();            }            finally            {                semaphore.Release();            }        }, null, delay, interval);    }}以下是调度程序类:internal class Scheduler : IScheduler{    private readonly ILogger _logger;    private readonly ConcurrentDictionary<string, IJob> _timers = new ConcurrentDictionary<string, IJob>();    public Scheduler(ILogger logger)    {        _logger = logger;    }    public IJob ScheduleAsync(string jobName, Func<Task<JobStatus>> action, TimeSpan interval, TimeSpan delay = default(TimeSpan))    {        if (!_timers.ContainsKey(jobName))        {            lock (_timers)            {                if (!_timers.ContainsKey(jobName))                    _timers.TryAdd(jobName, new TaskBasedJob(jobName, action, interval, delay, _logger));            }        }        return _timers[jobName];    }    public IReadOnlyDictionary<string, IJob> GetJobs()    {        return _timers;    }}在这个库里面,我有一个像下面这样的服务:所以这个服务的想法只是在被调用的字典_accessInfos和它的异步方法中获取一些数据。您可以在构造函数中看到我已经添加了获取数据的作业。
查看完整描述

1 回答

?
MMMHUHU

TA贡献1834条经验 获得超8个赞

Rajmond 的同事在这里。我弄清楚我们的问题。基本上,等待工作正常等等。我们的问题很简单,如果你这样做,IServiceCollection.BuildServiceProvider()你每次都会得到不同的范围(因此即使使用 Singleton 实例也会创建不同的对象)。试试这个的简单方法:


var serviceProvider1 = services.BuildServiceProvider();

var hashCode1 = serviceProvider1.GetService<IAccessInfoStore>().GetHashCode();

var hashCode2 = serviceProvider1.GetService<IAccessInfoStore>().GetHashCode();

var serviceProvider2 = services.BuildServiceProvider();

var hashCode3 = serviceProvider2.GetService<IAccessInfoStore>().GetHashCode();

var hashCode4 = serviceProvider2.GetService<IAccessInfoStore>().GetHashCode();

hashCode1andhashCode2相同,与hashCode3and相同hashCode4(因为单例),但hashCode1/hashCode2与hashCode3/hashCode4不同(因为不同的服务提供者)。


真正的修复可能是检查 IAccessInfoStore,它会在内部阻塞,直到作业第一次完成。


干杯!


查看完整回答
反对 回复 2021-11-21
  • 1 回答
  • 0 关注
  • 235 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信