如何取消深层嵌套的进程

Eri*_*sch 4 c# oop refactoring request-cancelling

我有一个类是"经理"类.其中一个功能是发出应该关闭该类的长时间运行过程的信号.它通过在类中设置一个名为"IsStopping"的布尔值来实现.

public class Foo
{
    bool isStoping

    void DoWork() {
        while (!isStopping)
        {
            // do work...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,DoWork()是一个巨大的功能,我决定重构它,并且作为该过程的一部分,将其中的一部分打破到其他类中.问题是,这些类中的一些还具有长时间运行的函数,需要检查isStopping是否为真.

public class Foo
{
    bool isStoping

    void DoWork() {
        while (!isStopping)
        {
            MoreWork mw = new MoreWork()
            mw.DoMoreWork() // possibly long running
            // do work...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我有什么选择?

我已经考虑通过引用传递isStopping,我不喜欢它,因为它需要有一个外部对象.我宁愿让额外的课程尽可能独立和免费.

我还考虑过使用isStopping属性,然后让它调用一个内部类可以订阅的事件,但这看起来过于复杂.

另一种选择是创建一个"进程取消令牌"类,类似于.net 4 Tasks使用的类,然后将该令牌传递给这些类.

你是怎么处理这种情况的?

编辑:

还要考虑MoreWork可能有一个实例化的EvenMoreWork对象,并在...上调用可能长时间运行的方法.我想我正在寻找的是一种方法,能够在调用树下发出任意数量的对象信号,告诉他们停止他们正在做的事情并清理和返回.

EDIT2:

感谢到目前为止的回复.似乎对使用的方法没有真正的共识,每个人都有不同的意见.看起来这应该是一种设计模式......

Jef*_*nal 5

你可以在这里走两条路:

1)您已经概述的解决方案:将信号机制传递给您的下级对象:bool(通过ref),父对象本身隐藏在接口中(Foo: IController在下面的示例中)或其他内容.子对象根据需要检查信号.

// Either in the MoreWork constructor
public MoreWork(IController controller) {
    this.controller = controller;
}

// Or in DoMoreWork, depending on your preferences
public void DoMoreWork(IController controller) {
    do {
        // More work here
    } while (!controller.IsStopping);
}
Run Code Online (Sandbox Code Playgroud)

2)转动它并使用观察者模式 - 这将允许您将下级对象与父项分离.如果我是手工完成(而不是使用事件),我会修改我的下级类来实现一个IStoppable接口,并让我的经理类告诉他们什么时候停止:

public interface IStoppable {
    void Stop();
}

public class MoreWork: IStoppable {
    bool isStopping = false;
    public void Stop() { isStopping = true; }
    public void DoMoreWork() {
        do {
            // More work here
        } while (!isStopping);
    }
}
Run Code Online (Sandbox Code Playgroud)

Foo 维护一个可停止的停止列表,并在其自己的停止方法中,将它们全部停止:

public void Stop() {
    this.isStopping = true;
    foreach(IStoppable stoppable in stoppables) {
        stoppable.Stop();
    }
}
Run Code Online (Sandbox Code Playgroud)