运行后台工作,但确保在任何给定时间只能运行一次 [英] Run background work, but ensure that this can only run once at any given time

查看:27
本文介绍了运行后台工作,但确保在任何给定时间只能运行一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想开始一些背景工作,我不必保留任何参考.开始然后忘记.但是我想确保这个后台工作在给定的任何时间只运行一次.

I want to kick off some background work, I do not have to keep any reference. Start and forget. However I want to make sure that this background work is only running once at any time given.

假设 StartBackgroundWork 只从一个线程调用,你能改进这个解决方案吗?你觉得这有什么问题吗?

Assuming that StartBackgroundWork is only ever called from one thread, can you improve this solution? Do you see any problems with this?

private bool _busy;

private void StartBackgroundWork()
{
    if(_busy)
    {
        return;
    }
    _busy = true;
    Task.Factory.StartNew(() => {
        try
        {
            // Do work
        }
        finally
        {
            _busy = false;
        }
    }, TaskCreationOptions.LongRunning);
}

在这种情况下,我应该避免使用 Task 吗?

Should I avoid using a Taskin this scenario?

推荐答案

这种方法可能会发生的一个问题是,如果 StartBackgroundWork 调用的时间非常接近后台任务刚刚完成的时间清理,然后:

One problem that can happen with this approach that if a StartBackgroundWork call is made very close in time to when the background task was just cleaning up, then:

_busy = false; -happens-before- if(_busy)

可能不会被保留.所以你可能会错过一些触发器.

may not be preserved. So you may miss some triggers.

只要 StartBackgroundWork ... 只从一个线程调用 ... 你不会有重叠的执行,但是当这个条件被违反时,安全去.请注意,此代码将来可能会维护,并且有人可能会在不考虑(或理解)线程影响的情况下调用该方法.对于 Web 应用程序,这种类型的保证尤其困难.

As long as StartBackgroundWork ...is only ever called from one thread... you will not have overlapping executions, but the moment this condition is violated, the safety goes. Do note that this code might be maintained in future, and someone may call that method without considering (or understanding) threading implications. This type of guarantee is especially difficult to make for web applications.

@GhostTW 提出的一种解决方案是在 _busy 下执行操作代码>锁.锁定确实会对性能产生一些影响,但易于维护.

One solution as proposed by @GhostTW is to perform the operations on _busy under lock. Locking does have some performance impact but is clean to maintain.

实现相同目标的一种聪明方法是将标志声明为 volatile.这是超快的,但它实现的方式是如此,嗯......扭曲,轻微的误用可能会造成弊大于利.如果性能不是微秒关键,那么建议使用锁定.

A smartass way to achieve the same objective would be to declare the flag as volatile. This is super fast but the way it achieves is so, umm... twisted, that a slight misuse can cause more harm than good. If performance is not microsecond critical, then recommend going with lock.

理想情况下,私有方法本身不需要是线程安全的,但是您的业务规则说明了什么是允许并行的,什么是不允许的.这使您的方法线程感知.是否使其线程安全是您的选择.根据您的业务规则的难易程度,您可能别无选择.要问的问题:(1) 如果我们确实错过了触发器怎么办?病人会死吗?(2) 如果任务最终并行运行两次怎么办?病人会死吗?(3) 如果有人查看我的代码怎么办?这会质疑我的咨询费吗?(最后一个是笑话)

Ideally a private method need not be threadsafe itself, but your business rules say something on what is allowed in parallel and what is not. That makes your method thread-aware. Making it thread-safe or not is your choice. Depending on how hard your business rule is, you might not have a choice. Questions to ask: (1) what if we do miss a trigger? Does a patient die? (2) What if the task does end up running twice in parallel? Does a patient die? (3) What if someone looks at my code? Will that question my consulting fees? (last one was a joke)

这篇关于运行后台工作,但确保在任何给定时间只能运行一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆