Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何确保在构造函数完成执行之前不调用任何内容_C# - Fatal编程技术网

C# 如何确保在构造函数完成执行之前不调用任何内容

C# 如何确保在构造函数完成执行之前不调用任何内容,c#,C#,考虑以下代码: using System.Threading; public class BaseClass { private Timer tmrWork; public BaseClass() { // read values from config tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval); } private void tmrWork_Tick(ob

考虑以下代码:

using System.Threading;
public class BaseClass {
    private Timer tmrWork;

    public BaseClass() {
        // read values from config
        tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
    }

    private void tmrWork_Tick(object state)
    {
        DoWork();
    } 

    protected abstract void DoWork();
}

public class ChildClass: BaseClass {
    public ChildClass() {
        // do a bunch of stuff here
        // potentially time consuming
    }

    protected override void DoWork() {
        // do stuff
    }
}
这里的意图是:基于配置值,从基类继承的类将在某个点调用名为DoWork的方法

因为该方法在单独的线程上被调用(由于使用System.Threading.Timer),所以有时会在ChildClass构造函数完成执行之前调用DoWork

在调用DoWork之前,如何确保子构造函数已完成?

另外,代码在Windows服务中。

这是我能想到的最简单的代码


public class BaseClass {
    private Timer tmrWork;
    protected bool IsReady;

    public BaseClass() {
        // read values from config
        tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
    }

    private void tmrWork_Tick(object state)
    {
        if (IsReady)
            DoWork();
    } 

    protected abstract void DoWork();
}

public class ChildClass: BaseClass {
    public ChildClass() {
        // do a bunch of stuff here
        // potentially time consuming
        IsReady = true;
    }

    protected override void DoWork() {
        // do stuff
    }
}
或者最好是制作一个现成的抽象方法,让孩子们去实现它。在上面的解决方案(以及Daniel的答案)中,总是有可能子类忘记设置标志(调用Initialize)

但我真的认为你的设计可能有问题。我不认为基类应该包含计时器。这样你就可以


新的子类();

现在突然有一些线程在后台做一些工作。 在我看来,计时器是一种运行作业的基础结构代码,这些作业在不同的类中实现,因此应该从基类中提取出来。当前的解决方案也不可测试


当然,我可能错了,因为我不知道真正的代码在做什么。

这是我能想到的最简单的方法


public class BaseClass {
    private Timer tmrWork;
    protected bool IsReady;

    public BaseClass() {
        // read values from config
        tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
    }

    private void tmrWork_Tick(object state)
    {
        if (IsReady)
            DoWork();
    } 

    protected abstract void DoWork();
}

public class ChildClass: BaseClass {
    public ChildClass() {
        // do a bunch of stuff here
        // potentially time consuming
        IsReady = true;
    }

    protected override void DoWork() {
        // do stuff
    }
}
或者最好是制作一个现成的抽象方法,让孩子们去实现它。在上面的解决方案(以及Daniel的答案)中,总是有可能子类忘记设置标志(调用Initialize)

但我真的认为你的设计可能有问题。我不认为基类应该包含计时器。这样你就可以


新的子类();

现在突然有一些线程在后台做一些工作。 在我看来,计时器是一种运行作业的基础结构代码,这些作业在不同的类中实现,因此应该从基类中提取出来。当前的解决方案也不可测试


当然,我可能错了,因为我不知道真正的代码在做什么。

构造函数的执行顺序与初始化器的执行顺序相反,所以我会在初始化器中进行设置工作

public class BaseClass {
    private Timer tmrWork;

    public BaseClass() {
        // read values from config
        tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
        lock (syncObject)
            Init();
    }

    protected abstract void Init();

    private void tmrWork_Tick(object state)
    {
        lock (syncObject)
            DoWork();
    } 

    protected abstract void DoWork();
}


public class ChildClass: BaseClass {
    private object syncObject = new object();

    protected override void Init() {
        lock (syncObject) {
            // do a bunch of stuff here
            // potentially time consuming
        }
    }

    protected override void DoWork() {
        // do stuff
    }
}

构造函数的执行顺序与初始化器相反,所以我会在初始化器中进行设置工作

public class BaseClass {
    private Timer tmrWork;

    public BaseClass() {
        // read values from config
        tmrWork = new Timer(tmrWork_Tick, null, 1, SomeInterval);
        lock (syncObject)
            Init();
    }

    protected abstract void Init();

    private void tmrWork_Tick(object state)
    {
        lock (syncObject)
            DoWork();
    } 

    protected abstract void DoWork();
}


public class ChildClass: BaseClass {
    private object syncObject = new object();

    protected override void Init() {
        lock (syncObject) {
            // do a bunch of stuff here
            // potentially time consuming
        }
    }

    protected override void DoWork() {
        // do stuff
    }
}

最安全的方法是在构造对象时不初始化计时器,而是提供
Enabled
属性或
Start()
方法,在对象完全初始化后显式启动计时器。此属性/方法由创建新对象的代码设置/调用,而不是从构造函数本身中设置/调用。

最安全的方法是在构建对象时不初始化计时器,而是提供启用的
属性或
启动()
方法,在对象完全初始化后显式启动计时器。此属性/方法由创建新对象的代码设置/调用,而不是从构造函数本身中设置/调用。

我希望子客户端类不必考虑执行DoWork的所有复杂性。我想要的模型是程序员重写DoWork方法,而不必考虑调用它的所有复杂性。哦,我明白了。因此,实际上锁应该放在
tmrWork\u Tick
中,然后是计算派生构造函数的执行顺序的情况。肯定会有办法的。我希望子客户端类不必考虑如何执行DoWork的所有复杂性。我想要的模型是程序员重写DoWork方法,而不必考虑调用它的所有复杂性。哦,我明白了。因此,实际上锁应该放在
tmrWork\u Tick
中,然后是计算派生构造函数的执行顺序的情况。肯定会有办法的。