微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 AsyncEx 检查另一个线程是否在锁定部分内?

如何解决如何使用 AsyncEx 检查另一个线程是否在锁定部分内?

我刚刚开始使用 Nito.AsyncEx 包和 AsyncLock 而不是普通的 lock() { ... } 部分,我在锁定部分中有 async 调用(因为您不能在这种情况下将 lock() 用于 good reasons 我刚刚读过)。这是我从 Hangfire 运行的工作中。我们称之为“工人”线程。

在另一个线程中,来自 ASP.NET 控制器,我想检查是否有当前正在锁定部分中执行的线程。如果锁定部分中没有线程,那么我将通过 Hangfire 安排后台作业。如果锁定部分已经有一个线程,那么我不想安排另一个线程。 (是的,这听起来可能有点奇怪,但那是另一回事了)。

有没有办法使用 Nito.AsyncEx 对象来检查这一点,还是应该在锁定部分的开头设置一个标志并在结尾取消设置?

例如我想要这个:

public async Task DoAJobInTheBackground(string queueName,int someParam)
{ 
    // do other stuff...

    // Ensure I'm the only job in this section
    using (await _asyncLock.LockAsync())
    {           
        await _aService.CallSomethingAsync());           
    }

    // do other stuff...
}

并从控制器调用的服务中使用我想象的方法 IsSomeoneInThereNow()

public void ScheduleAJobUnlessOneIsRunning(string queueName,int someParam)
{ 

    if (!_asyncLock.IsSomeoneInThereNow())
    {
        _backgroundJobClient.Enqueue<MyJob>(x => 
            x.DoAJobInTheBackground(queueName,someParam));
    }

}

但到目前为止我只能看到如何使用单独的变量来做到这一点(想象 _isAnybodyInHere一个 thread-safe bool 或者我使用了 Interlocked):

public async Task DoAJobInTheBackground(string queueName,int someParam)
{ 
    // do other stuff...

    // Ensure I'm the only job in this section
    using (await _asyncLock.LockAsync())
    {
        try
        {
            _isAnybodyInHere = true; 
            await _aService.CallSomethingAsync());
        }
        finally
        {
            _isAnybodyInHere = false; 
        }
    }

    // do other stuff...
}

来自控制器调用的服务:

public void ScheduleAJobUnlessOneIsRunning(string queueName,int someParam)
{ 

    if (!_isAnybodyInHere)
    {
        _backgroundJobClient.Enqueue<MyJob>(x => 
            x.DoAJobInTheBackground(queueName,someParam));
    }

}

真的感觉应该有更好的方法AsyncLock doc says

您可以使用 already-cancelled CancellationToken 调用 Lock 或 LockAsync 尝试立即获取 AsyncLock 无需实际进入等待队列。

但我不明白如何做到这一点,至少使用同步 Lock 方法

解决方法

我不明白该怎么做

您可以创建一个新的 const nexts = []; par.next('li').foreach(function (elem) { if (elem.hasClass('level-0') && nexts.length > 0) return false; // break loop if (elem.hasClass('level-1')) nexts.push(elem); // add li element }); 并传递 CancellationToken 来创建一个已经取消的:

true

如果锁定已被持有,则对 using (_asyncLock.Lock(new CancellationToken(canceled: true))) { ... } 的调用将抛出。

也就是说,我认为这不是解决您问题的好方法。总是有可能后台作业即将完成,控制器检查锁并确定它被持有,然后后台作业释放锁。在这种情况下,控制器不会触发后台作业。

,

您必须永远(!)对任何其他线程或进程做出任何假设!

在此特定示例中,您必须做的是“安排另一项工作”,除非您已经这样做了。 (为了避免“分叉炸弹”。) 那么,作业一旦真正开始执行,就必须决定:“我应该这样做吗?”如果不是,作业悄悄退出。

或者——也许这里的实际问题是:“已经有其他人≤scheduled_this_job≥?”

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?