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
中,然后是计算派生构造函数的执行顺序的情况。肯定会有办法的。