Module State

本文详细介绍了MFC中ModuleState的概念及其子类,包括AFX_MODULE_STATE、_AFX_BASE_MODULE_STATE和_AFX_DLL_MODULE_STATE等,并解释了如何通过AfxGetModuleState等函数获取这些状态信息。

4. Module State

Module State保存着和Module相关的状态信息。Module是Windows的术语,代表任何一个可执行的代码文件, EXE和DLL都是Module的一种。Module State有下面几种:

1.     AFX_MODULE_STATE,保存MODULE的信息,是_AFX_BASE_MODULE_STATE和_AFX_DLL_MODULE_STATE的基类

2.     _AFX_BASE_MODULE_STATE,保存MFC Module的状态信息,没有定义其他的成员

3.     _AFX_DLL_MODULE_STATE,保存DLL的状态信息,没有定义其他的成员

4.     AFX_MODULE_THREAD_STATE,保存主线程的有关状态信息,虽然AFX_MODULE_THREAD_STATE是保存的线程的状态信息,但是它只保存Module的主线程的状态信息,所以可以看作是Module State的一种。

这些Module State保存了MFC中的大量重要信息:

1.     CWinApp指针

2.     实例句柄

3.     资源Module的句柄

4.     句柄表

5.     OLE相关信息

6.     窗口过程

7.     Activation Context

8.     ……

 

4.1 AFX_MODULE_STATE

AFX_MODULE_STATE的定义如下:

 

// AFX_MODULE_STATE (global data for a module)

class AFX_MODULE_STATE : public CNoTrackObject

{

public:

#ifdef _AFXDLL

       AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion,

              BOOL bSystem = FALSE);

#else

       explicit AFX_MODULE_STATE(BOOL bDLL);

#endif

       ~AFX_MODULE_STATE();

 

       CWinApp* m_pCurrentWinApp;

       HINSTANCE m_hCurrentInstanceHandle;

       HINSTANCE m_hCurrentResourceHandle;

       LPCTSTR m_lpszCurrentAppName;

       // …… 其他成员,从略

};

 

可以看到:

1.     AFX_MODULE_STATE从CNoTrackObject继承。CNoTrackObject定义了自己的new/delete保证自己不会被各种调试版本的new/delete来Track,以免自己被错误的当作Leak。

2.     AFX_MODULE_STATE在DLL和非DLL(也就是EXE)的情况下具有不同的构造函数(和成员)

3.     AFX_MODULE_STATE在成员中保存了一些和Module相关的重要信息

实际上,AFX_MODULE_STATE并没有被直接使用,而是作为_AFX_BASE_MODULE_STATE和_AFX_DLL_MODULE_STATE的基类:

_AFX_BASE_MODULE_STATE被用于Module,其定义如下:

 

class _AFX_BASE_MODULE_STATE : public AFX_MODULE_STATE

{

public:

#ifdef _AFXDLL

       _AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcBase, _MFC_VER)

#else

       _AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE)

#endif

              { }

};

 

PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)

 

_AFX_DLL_MODULE_STATE和_AFX_BASE_MODULE_STATE类似,只是仅用于DLL:

 

class _AFX_DLL_MODULE_STATE : public AFX_MODULE_STATE

{

public:

       _AFX_DLL_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcDllStatic, _MFC_VER)

              { }

};

 

static _AFX_DLL_MODULE_STATE afxModuleState;

 

这两个class都没有定义额外的成员,比较简单,只是传入到基类AFX_MODULE_STATE的参数不同。此外,他们定义的方式不太一样,前者使用的是PROCESS_LOCAL宏,定义了一个变量_afxBaseModuleState。后者只是简单的定义了一个static变量afxModuleState。

 

下面这些函数可以用来获得Module的State:

1.     AfxGetModuleState

AfxGetModuleState首先获得_afxThreadState的m_pModuleState,如果当前的Thread State的m_pModuleState返回NULL,说明当前的Thread State没有正确的初始化(通常的原因是创建线程的时候调用的是CreateThread函数而非AfxBeginThread),则使用_afxBaseModuleState。

 

AFX_MODULE_STATE* AFXAPI AfxGetModuleState()

{

       _AFX_THREAD_STATE* pState = _afxThreadState;

       ENSURE(pState);

       AFX_MODULE_STATE* pResult;

       if (pState->m_pModuleState != NULL)

       {

              // thread state's module state serves as override

              pResult = pState->m_pModuleState;

       }

       else

       {

              // otherwise, use global app state

              pResult = _afxBaseModuleState.GetData();

       }

       ENSURE(pResult != NULL);

       return pResult;

}

 

 

_afxBaseModuleState是用PROCESS_LOCAL定义的:

 

PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)

 

它代表整个MFC Module的State。当你的程序是动态链接到MFC DLL的时候,该State只有一份。如果你的程序是静态链接到MFC的话,有几个模块(EXE/DLL)静态链接到MFC,MFC的代码就有几份,那么_afxBaseModuleState也就有几份。

 

2.     AfxGetStaticModuleState

AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module State。

 

#ifdef _AFXDLL

 

static _AFX_DLL_MODULE_STATE afxModuleState;

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = &afxModuleState;

       return pModuleState;

}

 

#else

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

       return pModuleState;

}

#endif

 

 

3.     AfxGetAppModuleState

AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:

 

AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()

{

       return _afxBaseModuleState.GetData();

}

 

从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。

ily: 宋体; mso-fareast-theme-font: minor-fareast">_afxBaseModuleState也就有几份。

 

 

2.     AfxGetStaticModuleState

AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module State。

 

#ifdef _AFXDLL

 

static _AFX_DLL_MODULE_STATE afxModuleState;

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = &afxModuleState;

       return pModuleState;

}

 

#else

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

       return pModuleState;

}

#endif

 

 

3.     AfxGetAppModuleState

AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:

 

AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()

{

       return _afxBaseModuleState.GetData();

}

 

从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。

ily: 宋体; mso-fareast-theme-font: minor-fareast">_afxBaseModuleState也就有几份。

 

 

2.     AfxGetStaticModuleState

AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module State。

 

#ifdef _AFXDLL

 

static _AFX_DLL_MODULE_STATE afxModuleState;

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = &afxModuleState;

       return pModuleState;

}

 

#else

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

       return pModuleState;

}

#endif

 

 

3.     AfxGetAppModuleState

AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:

 

AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()

{

       return _afxBaseModuleState.GetData();

}

 

从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。

ily: 宋体; mso-fareast-theme-font: minor-fareast">_afxBaseModuleState也就有几份。

 

 

2.     AfxGetStaticModuleState

AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module State。

 

#ifdef _AFXDLL

 

static _AFX_DLL_MODULE_STATE afxModuleState;

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = &afxModuleState;

       return pModuleState;

}

 

#else

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

       return pModuleState;

}

#endif

 

 

3.     AfxGetAppModuleState

AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:

 

AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()

{

       return _afxBaseModuleState.GetData();

}

 

从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。

public class ManagerAction : BaseAction public override void Start() { // occupy modules //// this.MainModule.CurActionGroup = this.GroupID; foreach (Module module in this.AttachedModules) { module.CurActionGroup = this.GroupID; } base.Start(); // update state to ActionState.Running } public class AttachedAction : BaseAction public override void Start() { if (this.MainModule.ExecuteAction(this)) { base.Start(); // <> only update act-state to 'Running' when rmt-service-call successfully sent } // <> else, act-state will switch to 'Aborted' } BaseAction public virtual void Start() { this.State = ActionState.Running; this.mStartTime = DateTime.Now; } class CleanOnGoAction : ManagerAction public override void Start() { // update attached actions parameters //// foreach (AttachedAction aa in this.mAttachedActions) { // <><> yangy 20181025: Clean on go, use '*' as 'empty next recipe ID', avoid MEC run CleanOnGo service with empty string failed (IAP: Wrong number of input parameters). // if (string.IsNullOrEmpty(aa.Params)) { aa.Params = "*"; } } base.Start(); } public void CheckActionList() { // <><><> maybe cause SKIP 'Aborting/Running' ManagerAction, put this before 'Start' //if (this.State == ModuleState.NotReady) //{ // return; // do nth //} ManagerAction grpToEnd = null; // 用于标记需要结束的动作组 lock (this.mActionList) { if (this.mActionList.Count == 0) { return; } // 获取当前动作组的 GroupID,如果 CurActionGroup 为 0,则使用 mActionList 中第一个动作的 GroupID int groupID = this.CurActionGroup == 0 ? this.mActionList[0].GroupID : this.CurActionGroup; // get first action foreach (BaseAction ba in this.mActionList) { //// check each action belongs to the same group one by one if (grpToEnd != null) { break; // group to end (abort/stop) has been found, 已经找到了需要结束的动作组 } if (ba.GroupID != groupID) { continue; // 'ba' does NOT belong to 'groupID' 当前动作不属于当前组 } switch (ba.State) { case ActionState.Ready: if (ba.CheckStart() && this.State != ModuleState.NotReady) // ManagerAction/AttachedAction do different thing { if (ba.IsManager && ba is CleanAction) { // <> assert: For 'ba' is 'Ready', so it must be the first one <> CleanAction ca = (CleanAction)ba; if (ca.Params == "*") // <><> NOT init { ProcessAction procAction = null; //PickAction pickAction = null; foreach (BaseAction ba1 in this.mActionList) { if (ba == ba1) { continue; } // <> check the first 'ProcessAction' // procAction = ba1 as ProcessAction; // 如果当前是CleanAction,从mActionList找到第一个 ProcessAction,并使用其参数初始化 CleanAction 的参数。 if (procAction != null) { //((CleanAction)ba).Params = procAction.Params; ca.Params = procAction.Params; // "ProcessRecipe,false" ca.Params = ca.Params.Remove(ca.Params.IndexOf(',')); // "ProcessRecipe" //ca.Params = string.Format("{0}@{1}", ca.Params, procAction.RouteName); ca.Params = string.Format("{0}@{1}@{2}", ca.Params, procAction.RouteName, procAction.MatSource); // 2024112<StartClean> xianghf_20211113 // <><><> yangy 20211129: every time rebuild 'ca.Params' OK ?? need test <><><> break; // found the first next recipe <> } } if (procAction == null) // xianghf_20211113, ??? 2024112<StartClean> { Coordinator.GetIns().GetLogger().InfoFormat("Module '{0}' SKIP reset clean action '{1}' Params for ProcessAction is NULL.", this.mFullName, ca.Name); } } } ba.Start(); // can start and module state is OK <> } break; case ActionState.Running: if (ba.IsManager && ba.CheckDone()) { grpToEnd = (ManagerAction)ba; // catch the manager, done it out of lock{}将 ba 转换为 ManagerAction 并赋值给 grpToEnd ba.Done(); // AttachedAction did this in remote service callback } break; case ActionState.Aborting: if (ba.IsManager && ba.CheckAborted()) { grpToEnd = (ManagerAction)ba; // catch the manager, aborted it out of lock{} ba.Aborted(); // AttachedAction did this in remote service callback 标记动作已被中止 } break; default: break; } // end switch } // end foreach }// end lock if (grpToEnd != null) { grpToEnd.Release(); // end the group <> } } CheckActionList中的ba.Start()如何调用 ba是cleanongoaction
最新发布
08-30
<think>好的,我现在需要回答用户的问题:“CheckActionList中的ba.Start()如何调用 ba是cleanongoaction”。首先,我需要仔细理解用户提供的代码,特别是CheckActionList方法和CleanOnGoAction类的结构。 首先,用户给出的代码中有几个类:ManagerAction、AttachedAction、BaseAction、CleanOnGoAction,以及CheckActionList方法。CheckActionList方法中有一个循环遍历mActionList中的每个BaseAction实例(ba),并根据其状态执行不同的操作。用户的问题是,当ba是CleanOnGoAction实例时,ba.Start()是如何被调用的。 我需要先理清CleanOnGoAction的继承关系。根据代码,CleanOnGoAction继承自ManagerAction,而ManagerAction又继承自BaseAction。因此,CleanOnGoAction是BaseAction的子类,具有多态性。在CheckActionList中,ba被声明为BaseAction类型,但实际可能指向其子类的实例,包括CleanOnGoAction。 接下来,查看CheckActionList中的逻辑。在foreach循环中,每个ba都会被检查其状态。当ba的状态是ActionState.Ready时,会调用ba.Start()。这里的关键是多态性:虽然ba是BaseAction类型,但实际调用的Start()方法取决于其运行时类型。如果ba是CleanOnGoAction实例,那么调用的是CleanOnGoAction.Start()方法。 现在需要确认CleanOnGoAction的Start()方法是否覆盖了BaseAction的Start()。根据用户提供的代码,CleanOnGoAction确实覆盖了Start()方法,其中包含设置参数并调用base.Start()。因此,当ba是CleanOnGoAction时,调用ba.Start()会执行CleanOnGoAction的Start()方法,而不是BaseAction或ManagerAction的版本。 另外,用户提到在CheckActionList中,当ba是CleanOnGoAction时,如何触发其Start()。需要确认在CheckActionList的循环中,是否有可能将CleanOnGoAction实例添加到mActionList中,并且其状态是否为Ready。根据代码中的逻辑,当ba.State == ActionState.Ready且满足其他条件时,才会调用Start()。 还需要注意,在CheckActionList中,当处理CleanAction(可能是CleanOnGoAction的父类或相关类)时,会进行参数初始化,可能涉及从其他ProcessAction中获取参数。这部分代码可能影响CleanOnGoAction的参数设置,但具体是否相关需要进一步分析。 总结来说,当ba是CleanOnGoAction实例且处于Ready状态时,调用ba.Start()会触发其重写的Start()方法,设置参数并调用基类的Start(),从而更新状态为Running。 接下来需要确保回答准确,并涵盖多态性、继承关系、方法覆盖以及调用条件等方面。同时,需要按照用户要求,在回答末尾提出3-5个相关问题,确保不换行,符合格式要求。</think>在 `CheckActionList` 方法中,当 `ba` 是 `CleanOnGoAction` 实例时,`ba.Start()` 的调用流程如下: --- ### **1. 触发条件** - **状态检查**:`ba.State == ActionState.Ready`。 - **条件判断**:`ba.CheckStart()` 返回 `true`,且当前模块状态 `this.State != ModuleState.NotReady`。 - **类型匹配**:`ba` 实际是 `CleanOnGoAction` 实例(继承自 `ManagerAction`,而 `ManagerAction` 继承自 `BaseAction`)。 --- ### **2. 多态性调用** - **方法解析**: 由于 `CleanOnGoAction` 重写了 `Start()` 方法,当调用 `ba.Start()` 时,实际执行的是 `CleanOnGoAction.Start()`,而非基类的 `BaseAction.Start()`。 - **代码逻辑**: ```csharp // CleanOnGoAction.Start() 的实现 public override void Start() { foreach (AttachedAction aa in this.mAttachedActions) { if (string.IsNullOrEmpty(aa.Params)) { aa.Params = "*"; // 避免空参数导致远程调用失败 } } base.Start(); // 调用 ManagerAction.Start(),最终触发 BaseAction.Start() } ``` --- ### **3. 关键行为** - **参数初始化**: 在 `CleanOnGoAction.Start()` 中,遍历所有 `AttachedAction` 实例,若其参数为空,则设置为 `"*"`,确保后续远程调用(如 `MainModule.ExecuteAction`)不会因参数缺失而失败。 - **状态更新**: 调用 `base.Start()` 后,会执行 `ManagerAction.Start()` 和 `BaseAction.Start()`,将 `ba.State` 更新为 `ActionState.Running`,并记录开始时间。 --- ### **4. 示例场景** 假设 `ba` 是 `CleanOnGoAction` 实例: 1. **状态就绪**:`ba.State` 为 `Ready`,且 `CheckStart()` 返回 `true`。 2. **参数修正**:调用 `CleanOnGoAction.Start()`,将所有 `AttachedAction` 的空参数设为 `"*"`。 3. **状态更新**:调用 `base.Start()`,最终将 `ba.State` 设为 `Running`。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值