NSIS完整实例(含服务的安装,运行前卸载)

# NetHalt - NSIS installer script # Copyright (C) 2008 Daniel Collins <solemnwarning@solemnwarning.net> # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # #    * Redistributions of source code must retain the above copyright #      notice, this list of conditions and the following disclaimer. # #    * Redistributions in binary form must reproduce the above copyright #      notice, this list of conditions and the following disclaimer in the #      documentation and/or other materials provided with the distribution. # #    * Neither the name of the author nor the names of its contributors may #      be used to endorse or promote products derived from this software #      without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. !include MUI2.nsh !include LogicLib.nsh !include nsDialogs.nsh Name "NetHalt" OutFile "nhclient.exe" InstallDir $PROGRAMFILES\NetHalt InstallDirRegKey HKLM "SOFTWARE\NetHalt" "InstallDir" !define MUI_ABORTWARNING !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "COPYING" !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_LANGUAGE "English" Function .onInit    nsisos::osversion    ${If} $0 < 5        MessageBox MB_OK "Windows 2000 (NT 5.0) or greater is required"        Abort    ${EndIf} FunctionEnd # Do local install # Section "NetHalt"    SetShellVarContext all    SetOutPath $INSTDIR    # Stop all running nhtray.exe processes    #    StrCpy $0 "nhtray.exe"    KillProc::KillProcesses    # Check if the NetHalt service is installed    #    SimpleSC::ExistsService "nhclient"    Pop $0    # Stop+Remove the NetHalt service if it's installed    #    ${If} $0 == 0        DetailPrint "Stopping NetHalt Client service..."        SimpleSC::StopService "nhclient"        DetailPrint "Removing NetHalt Client service..."        SimpleSC::RemoveService "nhclient"    ${EndIf}    WriteRegStr HKLM "SOFTWARE\NetHalt" "InstallDir" $INSTDIR    cinst::reg_write "dword" "SOFTWARE\NetHalt" "use_server" "0"    cinst::reg_write "string" "SOFTWARE\NetHalt" "server_name" ""    cinst::reg_write "dword" "SOFTWARE\NetHalt" "server_port" "0"    cinst::reg_write "dword" "SOFTWARE\NetHalt" "server_refresh" "1800"    cinst::reg_write "dword" "SOFTWARE\NetHalt" "warning" "300"    cinst::reg_write "dword" "SOFTWARE\NetHalt" "abort" "0"    cinst::reg_write "dword" "SOFTWARE\NetHalt" "delay" "0"    cinst::reg_write "string" "SOFTWARE\NetHalt" "sdtimes" ""    WriteUninstaller "$INSTDIR\uninstall.exe"    File "src\nhclient.exe"    File "src\evlog.dll"    File "src\nhtray.exe"    File "src\nhconfig.exe"    # Add the event log source (evlog.dll) to the registry    #    WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\Eventlog\Application\NetHalt Client" "EventMessageFile" "$INSTDIR\evlog.dll"    WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\Eventlog\Application\NetHalt Client" "TypesSupported" 0x00000007    # Add the uninstaller to Add/Remove programs    #    WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NetHalt" "DisplayName" "NetHalt"    WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NetHalt" "UninstallString" "$INSTDIR\uninstall.exe"    WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NetHalt" "NoModify" 1    WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NetHalt" "NoRepair" 1    # Install and start the NetHalt service    # TODO: Check for errors    #    DetailPrint "Installing NetHalt Client service..."    SimpleSC::InstallService "nhclient" "NetHalt Client" "16" "2" "$INSTDIR\nhclient.exe" "" "" ""    DetailPrint "Starting NetHalt Client service..."    SimpleSC::StartService "nhclient"    # Add nhtray.exe to the registry to run at login    #    WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "NetHalt" "$INSTDIR\nhtray.exe"    # Launch nhtray.exe    #    Exec '"$INSTDIR\nhtray.exe"'    # Create shortcuts    #    CreateDirectory "$SMPROGRAMS\NetHalt"    CreateShortCut "$SMPROGRAMS\NetHalt\Tray Icon.lnk" "$INSTDIR\nhtray.exe"    CreateShortCut "$SMPROGRAMS\NetHalt\Configuration.lnk" "$INSTDIR\nhconfig.exe"    CreateShortCut "$SMPROGRAMS\NetHalt\Uninstall.lnk" "$INSTDIR\uninstall.exe" SectionEnd Function un.onInit    SetShellVarContext all    ReadRegStr $INSTDIR HKLM "SOFTWARE\NetHalt" "InstallDir"    MessageBox MB_YESNO "This will uninstall NetHalt, continue?" IDYES NoAbort    Abort    NoAbort: FunctionEnd Section "Uninstall"    # Stop and remove the NetHalt service    #    DetailPrint "Stopping NetHalt Client service..."    SimpleSC::StopService "nhclient"    DetailPrint "Removing NetHalt Client service..."    SimpleSC::RemoveService "nhclient"    # Stop all running nhtray.exe processes    #    StrCpy $0 "nhtray.exe"    KillProc::KillProcesses    # Delete shortcuts    #    Delete "$SMPROGRAMS\NetHalt\Tray Icon.lnk"    Delete "$SMPROGRAMS\NetHalt\Configuration.lnk"    Delete "$SMPROGRAMS\NetHalt\Un-Install.lnk"    Delete "$SMPROGRAMS\NetHalt"    DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "NetHalt"    DeleteRegKey HKLM "SYSTEM\CurrentControlSet\Services\Eventlog\Application\NetHalt Client"    DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NetHalt"    Delete "$INSTDIR\nhclient.exe"    Delete "$INSTDIR\evlog.dll"    Delete "$INSTDIR\nhtray.exe"    Delete "$INSTDIR\uninstall.exe"    RMDir $INSTDIR SectionEnd

从命令行测量.NET程序性能

可以使用命令行工具收集有关应用程序的性能信息。

在本文所述的示例中,收集 Microsoft Notepad 的性能信息,但可以使用相同的方法来分析任何进程。

先决条件

  • Visual Studio 2019 或更高版本

  • 熟悉命令行工具

  • 若要在未安装 Visual Studio 的远程计算机上收集性能信息,请在此远程计算机上安装 Visual Studio 远程工具。 工具版本必须与 Visual Studio 版本匹配。

收集性能数据

使用 Visual Studio 诊断 CLI 工具进行性能分析的工作原理是将性能分析工具与其中某个收集器代理一起附加到进程。 附加性能分析工具时,将开始诊断捕获并存储分析数据的会话,直到该工具停止,此时数据将导出到 .diagsession 文件中。 然后,可以在 Visual Studio 中打开此文件以分析结果。

  1. 启动 Notepad,并打开任务管理器来获取其进程 ID (PID)。 在任务管理器中,找到“详细信息”选项卡中的 PID。

  2. 打开命令提示符,切换到包含集合代理可执行文件的目录,通常在此处(对于 Visual Studio Enterprise)。

    <Visual Studio installation folder>\2019\Enterprise\Team Tools\DiagnosticsHub\Collector\

  3. 通过键入以下命令,启动 VSDiagnostics.exe。

    cmd
    VSDiagnostics.exe start <id> /attach:<pid> /loadConfig:<configFile>

    必须包含的参数是:

    例如,可以将以下命令用于 CPUUsageBase 代理,方法是按之前所述替换 pid。

    cmd
    VSDiagnostics.exe start 1 /attach:<pid> /loadConfig:AgentConfigs\CPUUsageLow.json
    • <id> 标识收集会话。 ID 必须为介于 1 - 255 之间的数字。

    • <pid>,要分析的进程的 PID 在本例中是在步骤 1 中找到的 PID。

    • <configFile>,要启动的集合代理的配置文件。 有关详细信息,请参阅代理的配置文件

  4. 重设 Notepad 大小,或在其中键入内容,以确保收集一些有趣的分析信息。

  5. 通过键入以下命令,停止收集会话并将输出发送到文件。

    cmd
    VSDiagnostics.exe stop <id> /output:<path to file>
  6. 找到上一个命令的 .diagsession 文件输出,并在 Visual Studio 中打开它(“文件” > “打开”)以检查收集的信息 。

    要分析结果,请参阅相应的性能工具文档。 例如,这可能是 CPU 使用情况.NET 对象分配工具数据库工具。

代理配置文件

集合代理是可互换的组件,可根据要测量的内容收集不同类型的数据。

为方便起见,建议将该信息存储在代理配置文件中。 配置文件是至少包含 .dll 的名称及其 COM CLSID 的 .json 文件 。 以下是可以在以下文件夹中找到的示例配置文件:

<Visual Studio installation folder>Team Tools\DiagnosticsHub\Collector\AgentConfigs\

请参阅以下链接以下载和查看代理配置文件:

CpuUsage 配置(基本/高/低),对应于为 CPU 使用情况分析工具收集的数据。 DotNetObjectAlloc 配置(基本/低),对应于为 .NET 对象分配工具收集的数据。

基本/低/高配置是指采样率。 例如,低为 100 样本/秒,高为 4000 样本/秒。

要使 VSDiagnostics.exe 工具可用于集合代理,需要用于相应代理的 DLL 和 COM CLSID。 代理可能还具有其他配置选项,这可以是配置文件中指定的任何选项,格式为正确转义的 JSON。

权限

要分析需要提升权限的应用程序,必须从提升的命令提示符执行操作。

工具下载

下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux (microsoft.com)

引用资料

从命令行测量性能 - Visual Studio (Windows) | Microsoft Docs

十大知识领域关键概念

1 项目整合管理的核心概念

项目整合管理的核心概念包括:

Δ 项目整合管理是项目经理的具体职责,不能委托或转移。项目经理要整合所有其他知识领域的成果,以提供与项目总体情况有关的信息。项目经理必须对整个项目承担最终责任。

Δ 项目和项目管理具有整合性质,大多数任务涉及不止一个知识领域。

Δ 项目管理过程组内部和项目管理过程组之间的过程存在迭代型关系。

Δ 项目整合管理指的是:

• 确保项目可交付成果的最终交付日期、项目生命周期及效益实现计划保持一致;

• 提供可实现项目目标的项目管理计划;

• 确保创造合适的知识以运用到项目中,并从项目中汲取知识;

• 管理项目绩效和项目活动的变更;

• 做出针对影响项目的关键变更的综合决策;

• 衡量和监督进展,并采取适当的措施;

• 收集、分析项目信息,并将其传递给有关的相关方;

• 完成全部项目工作,正式关闭各个阶段、合同以及整个项目;

• 管理可能需要的阶段过渡。

 

2 项目范围管理的核心概念

项目范围管理的核心概念包括:

Δ 范围可以指产品范围(产品、服务或成果具有的特性和功能),或项目范围(为交付具有特定特性和功能产品、服务或成果而开展的工作)。

Δ 项目生命周期的连续区间涵盖预测型、适应型或敏捷型。在预测型生命周期中,项目开始时就对项目可交付成果进行定义,对任何范围变化都要进行渐进管理;而在适应型或敏捷型生命周期中,可交付成果经过多次迭代,详细范围得到了定义,并且在每次迭代开始时完成审批。

Δ 应该根据项目管理计划来衡量项目范围的完成情况,根据产品需求来衡量产品范围的完成情况。

 

3 项目进度管理的核心概念

项目进度管理的核心概念包括:

Δ 项目进度规划提供项目以何种方式及何时在规定的项目范围内交付产品、服务和成果的详细计划。

Δ 项目进度计划是沟通和管理相关方期望的工具,以及制作绩效报告的基础。

Δ 在可能的情况下,应在整个项目期间保持项目进度计划的灵活性,以根据获得的知识、对风险的深入理解和增值活动调整计划。

 

4 项目成本管理的核心概念

项目成本管理的核心概念包括:

Δ 项目成本管理主要关注完成项目活动所需的资源成本,但它也要考虑到项目决策对后续多次使用、维护和支持项目可交付成果所需成本的影响。

Δ 不同的相关方会在不同的时间、用不同的方法测算项目成本,因此应明确考虑管理成本的相关方需求。

Δ 预测和分析项目产品的潜在财务绩效可能在项目以外进行,或作为项目成本管理的一部分。

 

5 项目质量管理的核心概念

项目质量管理的核心概念包括:

Δ 项目质量管理需要兼顾项目管理与项目可交付成果两个方面,它适用于所有项目,无论项目的可交付成果具有何种特性。质量的测量方法和技术则需视专门针对项目所产生的可交付成果类型而定。

Δ 质量和等级是不同的概念。质量是一系列内在特性满足要求的程度ISO 90001,而等级是对用途相同但技术特性不同的可交付成果的级别分类。项目经理及团队要负责权衡,以便同时达到所要求的质量与等级水平。

Δ 预防胜于检查。最好是在设计时考虑可交付成果的质量,而不是在检查时发现质量问题。预防错误的成本通常远低于在检查或使用中发现并纠正错误的成本。

Δ 项目经理可能需要熟悉抽样。属性抽样的结果为合格或不合格,而变量抽样指的是在连续的量表上标明结果所处的位置,以表明合格的程度。

Δ 很多项目会为项目和产品衡量确立公差(结果的可接受范围)和控制界限(在统计意义上稳定的过程或过程绩效的普通差异的边界)。

Δ 质量成本 (COQ) 包括在产品生命周期中为预防不符合要求、为评价产品或服务是否符合要求,以及因未达到要求(返工)而发生的所有成本。质量成本通常关注项目集管理、项目组合管理、PMO 或运营。

Δ 当质量整合到项目和产品规划和设计中时,以及组织文化意识致力于提高质量时,就能达成最有效的质量管理。

 

6项目资源管理的核心概念

项目资源管理的核心概念包括:

Δ 项目资源包括物质资源(设备、材料、设施和基础设施)和团队资源(担任项目角色及承担相关职责的人员)。

Δ 管理团队资源和物质资源需要不同的技能和能力。

Δ 项目经理应同时是项目团队的主管和经理,而且应在聘用、管理、激励和授权团队成员方面做出适当的努力。

Δ 项目经理应了解影响团队的因素,例如,团队环境、团队成员所在的地理位置、相关方之间的沟通、组织变更管理、内部和外部政治、文化问题,以及组织的独特性,

Δ 项目经理还负责积极培养团队技能和能力,同时提高并保持团队的满意度和积极性。

Δ 物质资源管理着眼于以有效和高效的方式,分配和使用成功完成项目所需的物质资源,而无法有效管理和控制资源可能会降低项目顺利完工的概率。

 

7 项目沟通管理的核心概念

项目沟通管理的核心概念包括:

Δ 沟通是个人和/或小组之间有意或无意的信息交换过程,它描述的是,无论通过活动(如会议和演示等)或人为要素(如电子邮件、社交媒体、项目报告,或项目文档等),信息得以发送或接收的方式。项目沟通管理同时处理沟通过程、沟通活动和人为要素的管理。

Δ 有效的沟通会在不同相关方之间建立桥梁。相关方的差异通常会对项目执行或成果产生冲击或影响,因此,所有沟通必须清楚、简洁,这一点至关重要。

Δ 沟通活动包括内部和外部、正式和非正式、书面和口头。

Δ 沟通可上达至相关方高级管理层、下至团队成员,或横向至同级人员。这将影响信息的格式和内容。

Δ 通过语言、面部表情、示意和其他行动,沟通会有意识或无意识地发生,它包括为合适的人为沟通要素制定策略和计划,并应用技能以提升有效性。

Δ 为了防止误解和错误传达需做出努力,而沟通方式、信息传递方和信息都应经过认真选择。

Δ 有效的沟通依靠定义沟通的目的、理解信息接收方,以及对有效性进行监督。

 

8 项目风险管理的核心概念

项目风险管理的核心概念包括:

Δ 所有项目都有风险。组织应选择承担项目风险,以便创造价值并在风险和奖励之间取得平衡。

Δ 项目风险管理的目的在于,识别并管理其他项目管理过程中未处理的风险。

Δ 每个项目中都存在两个级别的风险:单个风险指的是一旦发生,会对一个或多个项目目标产生积极或消极影响的不确定事件或条件;整体项目风险指的是不确定性对项目整体的影响,它代表相关方面临的项目结果可能的积极和消极变化。这些影响源于包括单个风险在内的所有不确定性。项目风险管理过程要处理这两个项目级别上的风险。

Δ 一旦发生,单个风险可能对项目目标产生积极或消极的影响,而整体项目风险也有积极或消极之分。

Δ 在项目生命周期内,风险将持续涌现,所以,项目风险管理过程也应不断重复。

Δ 为了对特定项目的风险进行有效管理,项目团队需要认清在努力实现项目目标过程中,什么级别的风险敞口可以接受。这一点则由反映组织与项目相关者风险偏好的可测量风险临界值来确定。

 

9 项目采购管理的核心概念

项目采购管理的核心概念包括:

Δ 项目经理应足够熟悉采购过程,以便于制定与合同和合同关系有关的明智决策。

Δ 采购所涉及的协议描述双方,即买方和卖方之间的关系。协议可以简单或复杂,但采购方法应反映采购的复杂程度。协议可以是合同、服务水平协议、谅解、协议备忘录,或采购订单。

Δ 协议必须遵守当地、所在国及国际法中与合同有关的法律规定。

Δ 与采购专家合作以确保遵守组织政策的同时,项目经理还应确定所有采购都能满足项目的具体需要。

Δ 鉴于其法律约束力,协议需要经过更多的审批程序,通常会包括法务部,以确保它对产品、服务或卖方同意提供的成果有充分的描述,且其符合法律和法规关于采购的规定。

Δ 复杂项目可能需要同时或先后管理多个合同,而买卖方关系存在于项目的许多级别上,以及采购组织内部与外部组织之间。

 

10 项目相关方管理的核心概念

项目相关方管理的核心概念包括:

Δ 每个项目都有相关方,他们会受项目的积极或消极影响,或者能对项目施加积极或消极的影响。部分相关方影响项目工作或成果的能力有限,而有些相关方则会对项目及期望成果有重大影响。

Δ 项目经理和团队正确识别并以适当方式吸引所有相关方参与的能力,可以最终决定项目的成功或失败。

Δ 要提高成功的概率,相关方识别和吸引其参与的过程应该在项目章程中获得批准、项目经理已被任命,而且团队开始组建之后尽快启动。

Δ 有效相关方参与的关键在于,关注与所有相关方保持持续沟通,应该把相关方的满意程度视为关键项目目标来识别和管理。

Δ 为了实现项目效益,识别相关方和吸引相关方参与的过程需重复开展,而且应定期接受审查和更新,尤其在项目推进到新的阶段,或组织或更大范围内的相关方群体发生重大变化时。

 


常用术语

简写

英文全称

中文名称

备注

AC

Actual   Cost

实际成本


BAC

Budget   at Completion

完工预算


CCB

Change   Control Board

变更控制委员会


COQ

Cost Of   Quantity

质量成本


CPAF

Cost   Plus Award Fee

成本加奖励费用


CPFF

Cost   Plus Fixed Fee

成本加固定费用


CPI

Cost   Performance Index

成本绩效指数


CPIF

Cost   Plus Incentive Fee

成本加激励费用


CPM

Critical   Path Method

关键路径法


CV

Cost   Variance

成本偏差


EAC

Estimate   at Completion

完工估算


EF

Early   Finish Date

最早完成日期


ES

Early   Start Date

最早开始日期


ETC

Estimate   to Completion

完工尚需估算


EV

Earned   Value

挣值


EVM

Earned   Value Management

挣值管理


FF

Finish   to Finish

完成到完成


FFP

Firm   Fixed Price

固定总价


FPEPA

Fixed   Price with Economic Price Adjustment

总价加经济价格调整


FPIF

Fixed   Price Incentive Fee

总价加激励费用


FS

Finish   to Start

完成到开始


IFB

Invitation   For Bid

投标邀请书


LF

Last   Finish Date

最晚完成日期


LOE

Level   of Effort

支持型活动


LS

Last   Start Date

最晚开始日期


OBS

Organizational   Breakdown Structure

组织分解结构


PDM

Precedence   Diagramming Method

紧前关系绘图法


PMBOK

Project   Management Body of Knowledge

项目管理知识体系


PV

Planned   Value

计划价值


QFD

Quality Function   Deployment

质量功能展开


RACI

Responsible, Accountable, Consulted, Informed

执行、负责、咨询和知情


RAM

Responsibility   Assignment Matrix

责任分配矩阵


RBS

Risk   Breakdown Structure

风险分解结构


RFI

Request   for Information

信息邀请书


RFP

Request   for Proposal

建议邀请书


RFQ

Request   for Quotation

报价邀请书


SF

Start   to Finish

开始到完成


SOW

Statement   of Work

工作说明书


SPI

Schedule   Performance Index

进度绩效指数


SS

Start   to Start

开始到开始


SV

Schedule   Variance

进度偏差


SWOT

Strength,   Weakness, Opportunity,  Threaten

优势、劣势、机会与威胁


T&M

Time   and Material Contract

工料合同


WBS

Work   Breakdown Structure

工作分解结构


VAC

Variance   At Completion

完工偏差



Acceptance Criteria. 验收标准 可交付成果通过验收前必须满足的一系列条件。

Accepted Deliverables. 验收的可交付成果 项目产出的,且被项目客户或发起人确认为满足既定验收标准的产品、结果或能力。

Accuracy. 准确 在质量管理体系中,准确是指对正确程度的评估。

Acquire Resources. 获取资源 获取项目所需的团队成员、设施、设备、材料、用品和其他资源的过程。

Acquisition. 募集 获取执行项目活动所必需的人力资源和物质资源。募集将产生资源成本,但不一定是财务成本。

Activity. 活动 在进度计划中所列,并在项目过程中实施的工作组成部分。

Activity Attributes. 活动属性 进度活动所具备的多种属性,可以包含在活动清单中。活动属性包括活动编码、紧前活动、紧后活动、逻辑关系、提前量和滞后量、资源要求、强制日期、制约因素和假设条件。

Activity Duration. 活动持续时间 用日历单位表示的,进度活动从开始到完成的时间长度。参见持续时间

Activity Duration Estimates. 活动持续时间估算 对完成一项活动可能需要的时间的定量评估。

Activity List. 活动清单 一份记录进度活动的表格,包含活动描述、活动标识及足够详细的工作范围描述,以便项目团队成员了解所需执行的工作。

Activity-on-Node (AON). 活动节点法 见紧前关系绘图法(PDM

Actual Cost (AC). 实际成本 在给定时间段内,因执行项目活动而实际发生的成本。

Actual Duration. 实际持续时间 进度活动的实际开始日期与数据日期(如果该进度活动尚未完成)或实际完成日期(如果该进度活动已经完成)之间的日历时间。

Adaptive Life Cycle. 适应型生命周期 迭代型或增量型项目生命周期。

Affinity Diagrams. 亲和图 一种用来对大量创意进行分组,以便进一步审查和分析的技术。

Agreements. 协议 用于明确项目初步意向的任何文件或沟通,形式有合同、谅解备忘录(MOU)、协议书、口头协议和电子邮件等。

Alternative Analysis. 备选方案分析 一种对已识别的可选方案进行评估的技术,用来决定选择哪种方案或使用何种方法来执行项目工作。

Analogous Estimating. 类比估算 使用相似活动或项目的历史数据,来估算当前活动或项目的持续时间或成本的技术。

Analytical Techniques. 分析技术 根据可能的项目或环境变量变化及它们与其他变量之间的关系,对潜在后果进行评估、分析和预测的各种技术。

Assumption. 假设 在规划过程中不需要验证即可视为正确、真实或确定的因素。

Assumption Log. 假设日志 在整个项目生命周期中用来记录所有假设条件和制约因素的项目文件。

Attribute Sampling. 属性抽样 检测质量的一种方法。

Authority. 职权 使用项目资源、花费资金、做出决策或给予批准的权力。

Backward Pass. 逆推法 关键路径法中的一种技术。在进度模型中,从项目完工日期出发,反向推导,计算最晚开始和最晚结束日期。

Bar Chart. 横道图 展示进度相关信息的一种图表方式。在典型的横道图中,进度活动或工作分解结构组件竖列于图的左侧,日期横排在图的顶端,而活动持续时间则以按日期定位的水平条形表示。见甘特图

Baseline. 基准 经批准的工作产品版本,只有通过正式的变更控制程序才能进行变更,并且用作与实际结果进行比较的依据。

Basis of Estimates. 估算依据 概述项目估算所用依据的支持性文件,如假设条件、制约因素、详细级别、估算区间和置信水平。

Benchmarking. 标杆对照 标杆对照是指将实际或计划的产品、流程和实践与其他可比组织的做法进行比较,以便识别最佳实践、形成改进意见,并为绩效考核提供依据。

Benefits Management Plan. 效益管理计划 对创造、提高和保持项目或项目集效益的过程进行定义的书面文件。

Bid Documents. 招标文件 用于从潜在卖方征集信息、报价或建议书的所有文件。

Bidder Conference. 投标人会议 在准备投标书或建议书之前,与潜在卖方举行的会议,以便保证所有潜在卖方对本项采购都有清楚且一致的理解。又称承包商会议、供应商会议或投标前会议。

Bottom-Up Estimating. 自下而上估算 估算项目持续时间或成本的一种方法,通过从下到上逐层汇总WBS组件的估算而得到项目估算。

Budget. 预算 经批准的估算,用于整个项目、任一工作分解结构组件或任一进度活动。

Budget at Completion (BAC). 完工预算 为将要执行的工作所建立的全部预算的总和。

Buffer. 缓冲 见储备

Business Case. 商业论证 文档化的经济可行性研究报告,用来对尚缺乏充分定义的所选方案的收益进行有效性论证,是启动后续项目管理活动的依据。

Business Value. 商业价值 从商业运作中获得的可量化净效益。效益可以是有形的、无形的或两者兼有之。

Cause and Effect Diagram. 因果图 一种分解技术,有助于追溯造成非预期结果的根本原因。

Change. 变更 对任何正式受控的可交付成果、项目管理计划组成部分或项目文件的修改。

Change Control. 变更控制 一个过程,用来识别、记录、批准或否决对项目文件、可交付成果或基准的修改。

Change Control Board (CCB). 变更控制委员会 一个正式组成的团体,负责审议、评价、批准、推迟或否决项目变更,以及记录和传达变更处理决定。

Change Control System. 变更控制系统 一套程序,描述了如何管理和控制针对项目可交付成果和文档的修改。

Change Control Tools. 变更控制工具 辅助变更管理和(或)配置管理的手动或自动的工具。这套工具至少能够支持变更控制委员会的活动。

Change Log. 变更日志 项目过程中所做变更及其当前状态的综合清单。

Change Management Plan. 变更管理计划 项目管理计划的一个组成部分,用以建立变更控制委员会,记录其具体权限,并说明如何实施变更控制系统。

Change Request. 变更请求 关于修改文档、可交付成果或基准的正式提议。

Charter. 章程 见项目章程

Checklist Analysis. 核对单分析 使用清单来系统审核材料的准确性及完整性的一种技术。

Checksheets. 核查表 在收集数据时用作查对清单的计数表格。

Claim. 索赔 根据具有法律约束力的合同条款,卖方向买方(或买方向卖方)提出的关于报酬、补偿或款项的请求、要求或主张,如针对某个有争议的变更。

Claims Administration. 索赔管理 对合同索赔进行处理、裁决和沟通的过程。

Close Project or Phase. 结束项目或阶段 终结项目、阶段或合同的所有活动的过程。

Closing Process Group. 收尾过程组 正式完成或结束项目、阶段或合同所执行的过程(组)。

Code of Accounts. 账户编码 用于唯一地识别工作分解结构每个组件的编号系统。

Collect Requirements. 收集需求 为实现项目目标而确定、记录并管理相关方的需要和要求的过程。

Colocation. 集中办公 为改善沟通和工作关系,提高工作效率,而让项目团队成员的工作地点彼此靠近的一种组织布局策略。

Communication Methods. 沟通方法 在项目相关方之间传递信息的系统化的程序、技术或过程。

Communication Models. 沟通模型 说明在项目中将如何开展沟通过程的描述、比喻或图形。

Communication Requirements Analysis. 沟通需求分析 一种分析技术,通过访谈、研讨会或借鉴以往项目经验教训等方式,来确定项目相关方对信息的需求。

Communications Management Plan. 沟通管理计划 项目、项目集或项目组合管理计划的组成部分,描述了项目信息将如何、何时、由谁来进行管理和传播。

Communication Styles Assessment. 沟通风格评估 规划沟通活动时,用于识别与相关方开展沟通的优选沟通方法、形式和内容的一种技术。

Communication Technology. 沟通技术 用于项目相关方之间传递信息的特定工具、系统或计算机程序等。

Conduct Procurements. 实施采购 获取卖方应答、选择卖方并授予合同的过程。

Configuration Management Plan. 配置管理计划 项目管理计划的一个组成部分,用以说明如何在配置控制之下识别和解释项目参数,以及如何记录和报告项目参数的变更。

Configuration Management System. 配置管理系统 用于跟踪项目参数和监控这些参数变更的程序的集合。

Conformance. 一致性 质量管理体系中的一个通用概念,表示所交付的结果处于某质量要求的可接受偏差界限之内。

Constraint. 制约因素 对项目、项目集、项目组合或过程的执行有影响的限制性因素。

Context Diagrams. 系统交互图 对产品范围的可视化描绘,显示业务系统(过程、设备、计算机系统等)及其与人和其他系统(行动者)之间的交互方式。

Contingency. 紧急情况 可能对项目执行产生影响的一个事件或情形,可用储备去应对。

Contingency Reserve. 应急储备 在进度或成本基准内,为主动应对,已知风险而分配的时间或资金。

Contingent Response Strategies. 应急应对策略 事先制定的,在某个特定触发条件发生时,可以启动的应对措施。

Contract. 合同 合同是指对双方都有约束力的协议,强制卖方提供规定的产品、服务或成果,以及强制买方支付相应的费用。

Contract Change Control System. 合同变更控制系统 用来收集、跟踪、裁定和沟通有关合同变更的系统。

Control. 控制 对比实际绩效与计划绩效,分析偏差,评估趋势以改进过程,评价可能的备选方案,并提出必要的纠正措施建议。

Control Account. 控制账户 一种管理控制点。在该控制点上,把范围、预算、实际成本和进度加以整合,并与挣值比较,以测量绩效。

Control Chart. 控制图 按时间顺序展示过程数据,并将这些数据与既定的控制界限相比较的一种图形。控制图有一条中心线,有助于观察图中的数据点向两边控制界限偏移的趋势。

Control Costs. 控制成本 监督项目状态,以更新项目成本和管理成本基准变更的过程。

Control Limits. 控制界限 在控制图中,中心线或均值两侧三个标准差(基于数据的正态分布)以内的区域,它反映了数据的预期变动范围。参见规格界限

Control Procurements. 控制采购 管理采购关系,监督合同绩效,实施必要的变更和纠偏,以及关闭合同的过程。

Control Quality. 控制质量 为了评估绩效,确保项目输出完整、正确,并满足客户期望,而监督和记录质量管理活动执行结果的过程。

Control Resources. 控制资源 确保按计划为项目分配资源,以及根据资源使用计划监督资源实际使用情况,并采取必要纠正措施的过程。

Control Schedule. 控制进度 监督项目状态,以更新项目进度和管理进度基准变更的过程。

Control Scope. 控制范围 监督项目和产品的范围状态,管理范围基准变更的过程。

Corrective Action. 纠正措施 为使项目工作绩效重新与项目管理计划一致,而进行的有目的的活动。

Cost Aggregation. 成本汇总 在项目工作分解结构的给定层次或给定成本控制账户上,对与各工作包相关的较低层次的成本估算进行汇总。

Cost Baseline. 成本基准 经过批准的、按时间段分配的项目预算,不包括任何管理储备,只有通过正式的变更控制程序才能进行变更,用作与实际结果进行比较的依据。

Cost-Benefit Analysis. 成本效益分析 用来比较项目成本与其带来的收益的财务分析工具。

Cost Management Plan. 成本管理计划 项目或项目集管理计划的组成部分,描述如何规划、安排和控制成本。

Cost of Quality (CoQ). 质量成本 在整个产品生命周期所产生的所有成本,即:为预防产品或服务不符合要求而进行的投资,为评估产品或服务是否符合要求而产生的成本,以及因产品或服务未达到要求而带来的损失。

Cost Performance Index (CPI). 成本绩效指数 测量预算资源的成本效率的一种指标,表示为挣值与实际成本之比。

Cost Plus Award Fee Contract (CPAF). 成本加奖励费用合同 合同的一种类型,向卖方支付已完工作的全部合法实际成本,再加上一笔奖励费用作为卖方的利润。

Cost Plus Fixed Fee Contract (CPFF). 成本加固定费用合同 成本补偿合同的一种类型,买方为卖方报销可列支成本(可列支成本由合同确定),再加上一笔固定数额的利润(费用)。

Cost Plus Incentive Fee Contract (CPIF). 成本加激励费用合同 成本补偿合同的一种类型,买方为卖方报销可列支成本(可列支成本由合同确定),并且卖方在达到规定绩效标准时赚取利润。

Cost-Reimbursable Contract. 成本补偿合同 合同类型的一种,向卖方支付实际成本加费用(通常代表卖方的利润)。

Cost Variance (CV). 成本偏差 在某个给定时间点,预算亏空或盈余量,表示为挣值与实际成本之差。

Crashing. 赶工 通过增加资源,以最小的成本代价来压缩进度工期的一种技术。

Create WBS. 创建工作分解结构 将项目可交付成果和项目工作分解为较小的、更易于管理的组件的过程。

Criteria. 准则/标准 各种标准、规则或测试,可据此做出判断或决定,或者据此评价产品、服务、成果或过程。

Critical Path. 关键路径 代表项目中最长路径的活动序列,决定了项目最短的可能持续时间。

Critical Path Activity. 关键路径活动 项目进度计划中,位于关键路径上的任何活动。

Critical Path Method (CPM). 关键路径法 在项目进度模型中,估算项目最短工期,确定逻辑网络路径的进度灵活性大小的一种方法。

Data. 数据 离散的、无序的、未处理的测量结果或原始观察结果。

Data Analysis Techniques. 数据分析技术 用来组织、评估和评价数据与信息的技术。

Data Date. 数据日期 记录项目状态的时间点。

Data Gathering Techniques. 数据收集技术 从各种渠道收集数据与信息的技术。

Data Representation Techniques. 数据表现技术 用于传递数据和信息的图形方式或其他方法。

Decision-Making Techniques. 决策技术 从不同备选方案选择行动方案的技术。

Decision Tree Analysis. 决策树分析 一种图形和计算技术,用来评估与一个决策相关的多个可选方案在不确定情形下的可能后果。

Decomposition. 分解 把项目范围和项目可交付成果逐步划分为更小、更便于管理的组成部分的技术。

Defect. 缺陷 项目组成部分中不能满足要求或规范,需要修补或更换的瑕疵或缺点。

Defect Repair. 缺陷补救 为了修正不一致产品或产品组件的有目的的活动。

Define Activities. 定义活动 识别和记录为完成项目可交付成果而须采取的具体行动的过程。

Define Scope. 定义范围 制定项目和产品详细描述的过程。

Deliverable. 可交付成果 为完成某一过程、阶段或项目而必须产出的任何独特并可核实的产品、成果或服务能力。

Dependency. 依赖关系 见逻辑关系

Determine Budget. 制定预算 汇总所有单个活动或工作包的估算成本,建立一个经批准的成本基准的过程。

Development Approach. 开发方法 在项目生命周期内用于创建并改进产品、服务或成果的方法,例如预测、迭代、增量、敏捷或混合型方法。

Develop Project Charter. 制定项目章程 编写一份正式批准项目并授权项目经理在项目活动中使用组织资源的文件的过程。

Develop Project Management Plan. 制定项目管理计划 定义、准备和协调项目计划的所有组成部分,并把它们整合为一份综合项目管理计划的过程。

Develop Schedule. 制定进度计划 分析活动顺序、持续时间、资源需求和进度制约因素,创建项目进度模型,从而落实项目执行和监控的过程。

Develop Team. 建设团队 提高工作能力,促进团队成员互动,改善团队整体氛围,以提高项目绩效的过程。

Diagramming Techniques. 图解技术 用逻辑链接来呈现信息以辅助理解的方法。

Direct and Manage Project Work. 指导与管理项目工作 为实现项目目标而领导和执行项目管理计划中所确定的工作,并实施已批准变更的过程。

Discrete Effort. 独立型活动 能够予以规划并测量,且会产出特定输出的活动。(附注:独立型活动是用于计算工作绩效的三种挣值管理(EVM)活动之一。)

Discretionary Dependency. 选择性依赖关系 基于某应用领域或项目方面对活动顺序的最佳实践而建立的依赖关系。

Documentation Reviews. 文件审查 收集大量信息并进行审查以确定其准确性及完整性的过程。

Duration. 持续时间 完成一个活动或工作分解结构组件所需要的工作时段总数,以小时、天或周表示。比较人力投入

Early Finish Date (EF). 最早完成日期 在关键路径法中,基于进度网络逻辑、数据日期和进度制约因素,某进度活动未完部分可能完成的最早时点。

Early Start Date (ES). 最早开始日期 在关键路径法中,基于进度网络逻辑、数据日期和进度制约因素,某进度活动未完部分可能开始的最早时点。

Earned Value (EV). 挣值 对已完成工作的测量,用该工作的批准预算来表示。

Earned Value Management. 挣值管理 将范围、进度和资源测量值综合起来,以评估项目绩效和进展的方法。

Effort. 人力投入 完成一个进度活动或工作分解结构组件所需要的人工单位数,通常以小时、天和周来表示。比较持续时间

Emotional Intelligence. 情商 识别、评估和管理个人情绪、他人情绪及团组群体情绪的能力。

Enterprise Environmental Factors. 事业环境因素 团队不能直接控制的,将对项目、项目集或项目组合产生影响、限制或指导作用的各种条件。

Estimate. 估算 对某一变量的可能数值或结果的定量评估,如项目成本、资源、人力投入或持续时间。

Estimate Activity Durations. 估算活动持续时间 根据资源估算的结果,估算完成单项活动所需工作时段数的过程。

Estimate Activity Resources. 估算活动资源 估算执行项目所需的团队资源,以及材料、设备和用品的类型和数量的过程。

Estimate at Completion (EAC). 完工估算 完成所有工作所需的预期总成本,等于截至目前的实际成本加上完工尚需估算。

Estimate Costs. 估算成本 对完成项目活动所需资源成本进行近似估算的过程。

Estimate to Complete (ETC). 完工尚需估算 完成所有剩余项目工作的预计成本。

Execute. 执行 指导、管理、实施和完成项目工作,产出可交付成果和工作绩效数据。

Executing Process Group. 执行过程组 完成项目管理计划中确定的工作,以满足项目要求的一组过程。

Expert Judgment. 专家判断 基于某应用领域、知识领域、学科和行业等的专业知识而做出的,关于当前活动的合理判断。这些专业知识可来自具有专业学历、知识、技能、经验或培训经历的任何小组或个人。

Explicit Knowledge. 显性知识 可以使用文字、数字、图片等符号进行编辑的知识。

External Dependency. 外部依赖关系 项目活动与非项目活动之间的关系。

Fallback Plan. 弹回计划 弹回计划包括一组备用的行动和任务,以便在主计划因问题、风险或其他原因而需要被废弃时采用。

Fast Tracking. 快速跟进 一种进度压缩技术,将正常情况下按顺序进行的活动或阶段改为至少是部分并行开展。

Fee. 费用 卖方所得补偿的一部分,代表利润。

Finish Date. 完成日期 与进度活动的完成相关联的时间点。通常带下列修饰词:实际、计划、估计、预计、最早、最晚、基准、目标或当前。

Finish-to-Finish (FF). 完成到完成 只有紧前活动完成,紧后活动才能完成的逻辑关系。

Finish-to-Start (FS). 完成到开始 只有紧前活动完成,紧后活动才能开始的逻辑关系。

Firm Fixed Price Contract (FFP). 固定总价合同 总价合同的一种类型。不考虑卖方成本,由买方向卖方支付事先确定的金额(由合同规定)。

Fishbone diagram. 鱼骨图 见因果图

Fixed-Price Contract. 总价合同 规定了为确定的工作范围所需支付的费用的协议,与完成工作的实际成本或人力投入无关。

Fixed Price Incentive Fee Contract (FPIF). 总价加激励费用合同 总价合同的一种类型。买方向卖方支付事先确定的金额(由合同规定),如果卖方满足了既定的绩效标准,则还可挣到额外的金额。

Fixed Price with Economic Price Adjustment Contract (FPEPA). 总价加经济价格调整合同 总价合同的一种类型,但合同中包含了特殊条款,允许根据条件变化,如通货膨胀、某些特殊商品的成本增加(或降低),以事先确定的方式对合同价格进行最终调整。

Float. 浮动时间 也叫时差。参见总浮动时间自由浮动时间

Flowchart. 流程图 对某系统内的一个或多个过程的输入、过程行为和输出的图形描述。

Focus Groups. 焦点小组 召集预定的相关方和主题专家,了解他们对所讨论的产品、服务或成果的期望和态度的一种启发式技术。

Forecast. 预测 根据已有的信息和知识,对项目未来的情况和事件进行的估算或预计。

Forward Pass. 顺推法 关键路径法中的一种技术。在进度模型中,从项目开始日期或某给定时点出发,正向推导,计算最早开始和最早结束日期。

Free Float. 自由浮动时间 在不延误任何紧后活动最早开始日期或违反进度制约因素的前提下,某进度活动可以推迟的时间量。

Functional Organization. 职能型组织 把员工按专业领域分组的一种组织架构,项目经理分配工作和使用资源的职权有限。

Funding Limit Reconciliation. 资金限制平衡 把项目资金支出计划与项目资金到位承诺进行对比,从而识别资金限制与计划支出之间的差异的过程。

Gantt Chart. 甘特图 展示进度信息的条形图。纵向列示活动,横向列示日期,用横条表示活动自开始日期至结束日期的持续时间。

Grade. 等级 用以区分功能相同但质量要求不同的对象的类别或级别。

Ground Rules. 基本规则 对项目团队成员的可接受行为的预期。

Histogram. 直方图 一种展示数字数据的条形图。

Historical Information. 历史信息 以往项目的文件和数据,包括项目档案、记录、函件、完结的合同和结束的项目。

Identify Risks. 识别风险 识别单个风险,以及整体风险的来源,并记录风险特点的过程。

Identify Stakeholders. 识别相关方 定期识别项目相关方,分析和记录他们的利益、参与度、相互依赖性、影响力和对项目成功的潜在影响的过程。

Implement Risk Responses. 实施风险应对 执行商定的风险应对计划的过程。

Imposed Date. 强制日期 强加于进度活动或进度里程碑的固定日期,一般采取不早于何时开始不晚于何时结束的形式。

Incentive Fee. 激励费用 与卖方的成本、进度或技术绩效相关联的财务激励。

Incremental Life Cycle. 增量型生命周期 一种适应型项目生命周期,它是通过在预定的时间区间内渐进增加产品功能的一系列迭代来产出可交付成果。只有在最后一次迭代之后,可交付成果具有了必要和足够的能力,才能被视为完整的。

Independent Estimates. 独立估算 使用第三方来获取和分析信息,以支持对成本、进度或其他事项的预测的过程。

Influence Diagram. 影响图 对变量与结果之间的因果关系、事件时间顺序及其他关系的图形表示。

Information. 信息 被组织或结构化的数据,并进一步为特定目的加以处理,使之在特定环境中具有意义和价值并且能够发挥作用。

Information Management Systems. 信息管理系统 用于在信息的生产者与消费者之间以实体或电子形式收集、存储和分发信息的设施、过程及程序。

Initiating Process Group. 启动过程组 定义一个新项目或现有项目的一个新阶段,授权开始该项目或阶段的一组过程。

Input. 输入 开始一个过程所必需的、来自项目内外的任何东西。可以是前一过程的输出。

Inspection. 检查 检查工作产品,以确定它是否符合书面标准。

Interpersonal and Team Skills. 人际关系与团队技能 用于有效地领导团队成员和其他相关方并与之进行互动的技能。

Interpersonal Skills. 人际关系技能 与他人建立并保持关系的技能。

Interviews. 访谈 通过与相关方直接交谈,来获取信息的正式或非正式方法。

Invitation for Bid (IFB). 投标邀请书 通常,本术语等同于建议邀请书。不过,在某些应用领域,其含义可能更狭窄或更具体。

Issue. 问题 可能对项目目标产生影响的当前条件或情形。

Issue Log. 问题日志 记录和监督问题信息的项目文件。

Iterative Life Cycle. 迭代型生命周期 一种项目生命周期,项目范围通常于项目生命周期的早期确定,但时间及成本估算将随着项目团队对产品理解的不断深入而定期修改。迭代方法是通过一系列循环来开发产品,而增量方法是渐进地增加产品的功能。

Knowledge. 知识 为了发挥新的经历和信息的作用,而使用的经验、价值观和信念、情景信息、直觉和洞察力的组合。

Lag. 滞后量 相对于紧前活动,紧后活动需要推迟的时间量。

Late Finish Date (LF). 最晚完成日期 在关键路径法中,基于进度网络逻辑、项目完成日期和进度制约因素,进度活动未完成部分可能的最晚完成时点。

Late Start Date (LS). 最晚开始日期 在关键路径法中,基于进度网络逻辑、项目完成日期和进度制约因素,进度活动未完成部分可能的最晚开始时点。

Lead. 提前量 相对于紧前活动,紧后活动可以提前的时间量。

Lessons Learned. 经验教训 项目过程中获得的知识,说明曾怎样处理某个项目事件或今后应如何处理,以改进未来绩效。

Lessons Learned Register. 经验教训登记册 用于记录在项目中所获知识的项目文件,它用于当前项目,并列入经验教训知识库。

Lessons Learned Repository. 经验教训知识库 存储从项目中获得的以往经验教训的信息库。

Level of Effort (LOE). 支持型活动 一种不产生明确的最终产品,而是按时间流逝来度量的活动。

Life Cycle. 生命周期 见项目生命周期

Log. 日志 对过程或活动实施期间的某些特定事项进行记录、描述或说明的文件。前面常加修饰词,如问题、变更或假设等。

Logical Relationship. 逻辑关系 两个活动之间,或者一个活动与一个里程碑之间的依赖关系。

Make-or-Buy Analysis. 自制或外购分析 收集和整理有关产品需求的数据,对包括采购产品或内部制造产品在内的多个可选方案进行分析的过程。

Make-or-Buy Decisions. 自制或外购决策 关于从外部采购或由内部制造某产品的决策。

Manage Communications. 管理沟通 管理沟通是确保及时且恰当地收集、生成、发布、存储、检索、管理、监督和最终处置项目信息的过程。

Management Reserve. 管理储备 在绩效测量基准之外,留作管理控制之用的一部分项目预算或项目时间。专为项目范围内不可预见的工作而预留。

Management Skills. 管理技能 对个人或群体进行规划、组织、指导和控制,以实现特定目标的能力。

Manage Project Knowledge. 管理项目知识 使用现有知识并生成新知识,以实现项目目标,并且帮助组织学习的过程。

Manage Quality. 管理质量 把组织的质量政策用于项目,并将质量管理计划转化为可执行的质量活动的过程。

Manage Stakeholder Engagement. 管理相关方参与 与相关方进行沟通和协作,以满足其需求与期望,解决问题,并促进相关方合理参与项目活动的过程。

Manage Team. 管理团队 跟踪团队成员工作表现,提供反馈,解决问题并管理团队变更,以优化项目绩效的过程。

Mandatory Dependency. 强制性依赖关系 合同要求的或工作的内在性质决定的依赖关系。

Master Schedule. 主进度计划 标明了主要可交付成果、主要工作分解结构组件和关键进度里程碑的概括性项目进度计划。参见里程碑进度计划

Matrix Diagrams. 矩阵图 一种质量管理和控制工具,使用矩阵结构对数据进行分析。在行列交叉的位置展示因素、原因和目标之间的关系强弱。

Matrix Organization. 矩阵型组织 由项目经理与职能经理共同负责安排工作优先级和指挥项目人员的一种组织架构。

Methodology. 方法论 由专门的从业人员所采用的做法、技术、程序和规则所组成的体系。

Milestone. 里程碑 项目、项目集或项目组合中的重要时点或事件。

Milestone Schedule. 里程碑进度计划 用于显示里程碑的计划实现日期的一种进度计划类型。参见主进度计划

Mind-Mapping. 思维导图 把从头脑风暴中获得的创意整合成一张图的技术,用以反映创意之间的共性与差异,激发新创意。

Monitor. 监督 收集项目绩效数据,计算绩效指标,并报告和发布绩效信息。

Monitor and Control Project Work. 监控项目工作 跟踪、审查和报告整体项目进展,以实现项目管理计划中确定的绩效目标的过程。

Monitor Communications. 监督沟通 确保满足项目及其相关方的信息需求的过程。

Monitoring and Controlling Process Group. 监控过程组 跟踪、审查和调整项目进展与绩效,识别必要的计划变更并启动相应变更的一组过程。

Monitor Risks. 监督风险 在整个项目期间,监督商定的风险应对计划的实施、跟踪已识别风险、识别和分析新风险,以及评估风险管理有效性的过程。

Monitor Stakeholder Engagement. 监督相关方参与 监督项目相关方关系,并通过修订参与策略和计划来引导相关方合理参与项目的过程。

Monte Carlo Simulation. 蒙特卡洛模拟 一种计算机模型分析技术,基于概率分布和概率分支进行许多次迭代,每次迭代都随机抽取输入数据。最终输出的是可能的项目结果的概率分布区间。

Multicriteria Decision Analysis. 多标准决策分析 该技术借助决策矩阵,用系统分析方法建立诸如风险水平、不确定性和价值收益等多种标准,从而对众多方案进行评估和排序。

Network. 网络 见项目进度网络图

Network Logic. 网络逻辑 项目进度网络图中的所有活动依赖关系。

Network Path. 网络路径 在项目进度网络图中,通过逻辑关系连接起来的一系列进度活动的序列。

Networking. 人际交往 与同一组织和不同组织中的人员建立联系和关系。

Node. 节点 在进度网络图上连接依赖关系线的一个点。

Nominal Group Technique. 名义小组技术 用于促进头脑风暴的一种技术,通过投票排列最有用的创意,以便进一步开展头脑风暴或优先排序。

Objective. 目标 工作所指向的事物,要达到的战略地位,要达到的目的,要取得的成果,要生产的产品,或者准备提供的服务。

Opportunity. 机会 对项目的一个或多个目标产生正面影响的风险。

Organizational Breakdown Structure (OBS). 组织分解结构 对项目组织的一种层级描述,展示了项目活动与执行这些活动的组织单元之间的关系。

Organizational Learning. 组织学习法 关于个人、群体和组织如何发展知识的方法。

Organizational Process Assets. 组织过程资产 执行组织所特有的并被其使用的计划、流程、政策、程序和知识库。

Output. 输出 某个过程所产生的产品、成果或服务。可能成为后续过程的输入。

Overall Project Risk. 整体项目风险 不确定性对项目整体的影响,它代表相关方面临的项目结果可能的正面和负面变异。这些影响源于包括单个风险在内的所有不确定性。

Parametric Estimating. 参数估算 基于历史数据和项目参数,使用某种算法来计算成本或持续时间的一种估算技术。

Path Convergence. 路径汇聚 表示一个进度活动拥有一个以上的紧前活动的一种关系。

Path Divergence. 路径分支 表示一个进度活动拥有一个以上的紧后活动的一种关系。

Percent Complete. 完成百分比 对某活动或工作分解结构组件的已完成工作量的百分比估算。

Performance Measurement Baseline (PMB). 绩效测量基准 整合在一起的范围、进度和成本基准,用来与项目执行情况相比较,以管理、测量和控制项目绩效。

Performance Reviews. 绩效审查 对照基准,对项目正在开展的工作的实际绩效进行测量、比较和分析的一种技术。

Perform Integrated Change Control. 实施整体变更控制 审查所有变更请求,批准变更,管理对可交付成果、组织过程资产、项目文件和项目管理计划的变更,并对变更处理结果进行沟通的过程。

Perform Qualitative Risk Analysis. 实施定性风险分析 通过评估单个项目风险发生的概率和影响以及其他特征,对风险进行优先排序,从而为后续分析或行动提供基础的过程。

Perform Quantitative Risk Analysis. 实施定量风险分析 就已识别的单个项目风险和不确定性的其他来源对项目整体目标的综合影响进行定量分析的过程。

Phase. 阶段 见项目阶段

Phase Gate. 阶段关口 为做出进入下个阶段、进行整改或结束项目或项目集的决定,而开展的阶段末审查。

Plan Communications Management. 规划沟通管理 基于每个相关方或小组的信息需求、可用的组织资产和项目需求,为项目沟通活动制定恰当的方法和计划的过程。

Plan Cost Management. 规划成本管理 确定如何估算、预算、管理、监督和控制项目成本的过程。

Planned Value (PV). 计划价值 为计划工作分配的经批准的预算。

Planning Package. 规划包 工作内容已知但详细进度活动未知的,低于控制账户的工作分解结构组件。参见控制账户

Planning Process Group. 规划过程组 明确项目范围,优化目标,为实现目标制定行动方案的一组过程。

Plan Procurement Management. 规划采购管理 记录项目采购决策,明确采购方法,识别潜在卖方的过程。

Plan Quality Management. 规划质量管理 识别项目及其可交付成果的质量要求和/或标准,并书面描述项目将如何证明符合质量要求的过程。

Plan Resource Management. 规划资源管理 定义如何估算、获取、管理和利用实物以及团队资源的过程。

Plan Risk Management. 规划风险管理 定义如何实施项目风险管理活动的过程。

Plan Risk Responses. 规划风险应对 为处理整体项目风险敞口,以及应对单个项目风险,而制定可选方案、选择应对策略并商定应对行动的过程。

Plan Schedule Management. 规划进度管理 为规划、编制、管理、执行和控制项目进度而制定政策、程序和文档的过程。

Plan Scope Management. 规划范围管理 为记录如何定义、确认和控制项目范围及产品范围,而创建范围管理计划的过程。

Plan Stakeholder Engagement. 规划相关方参与 根据相关方的需求、期望、利益和对项目的潜在影响,制定项目相关方参与项目的方法的过程。

Plurality. 相对多数原则 根据群体中相对多数人的意见做出决定,即便未能获得大多数人的同意。

Policy. 政策 组织所采用的一套结构化的行动模式,组织政策可以解释为一套治理组织行为的基本原则。

Portfolio. 项目组合 为实现战略目标而组合在一起管理的项目、项目集、子项目组合和运营工作。

Portfolio Management. 项目组合管理 为了实现战略目标而对一个或多个项目组合进行的集中管理。

Practice. 实践 有助于过程执行的某种特定类型的专业或管理活动,可能需要运用一种或多种技术及工具。

Precedence Diagramming Method (PDM). 紧前关系绘图法 创建进度模型的一种技术,用节点表示活动,用一种或多种逻辑关系连接活动,以显示活动的实施顺序。

Precedence Relationship. 紧前关系 用于紧前关系绘图法中的逻辑依赖关系。

Predecessor Activity. 紧前活动 在进度计划的逻辑路径中,排在非开始活动前面的活动。

Predictive Life Cycle. 预测型生命周期 项目生命周期的一种类型,在生命周期的早期阶段确定项目范围以及所需时间和成本。

Preventive Action. 预防措施 为确保项目工作的未来绩效符合项目管理计划,而进行的有目的的活动。

Probability and Impact Matrix. 概率和影响矩阵 把每个风险发生的概率和一旦发生对项目目标的影响映射起来的一种表格。

Procedure. 程序 用于达成稳定绩效或结果的某种既定方法,通常表现为执行某个过程的一系列特定步骤。

Process. 过程 旨在创造最终结果的系统化的系列活动,以便对一个或多个输入进行加工,生成一个或多个输出。

Procurement Audits. 采购审计 对合同和采购过程的完整性、正确性和有效性进行的审查。

Procurement Documents. 采购文件 在招投标活动中使用的文件,包括买方的投标邀请书、谈判邀请书、信息邀请书、报价邀请书、建议邀请书,以及卖方的应答。

Procurement Documentation. 采购文档 在签署、执行及结束一份协议时所用到的所有文件。采购文档中可能包括项目启动之前的文件。

Procurement Management Plan. 采购管理计划 项目或项目集管理计划的组成部分,说明项目团队将如何从执行组织外部获取货物和服务。

Procurement Statement of Work. 采购工作说明书 对拟采购项的详细描述,以便潜在卖方确定他们是否有能力提供这些产品、服务或成果。

Procurement Strategy. 采购策略 为了获得期望的结果,买方用来确定项目交付方式,以及具有法律约束力的协议的类型的方法。

Product. 产品 可以计量的人工制品,既可以是最终制品,也可以是组件制品。也可以用材料货物代指产品。参见可交付成果

Product Analysis. 产品分析 在以产品为可交付成果的项目上,用来定义范围的一种工具。通常,针对产品提问并回答,形成对将要生产的产品的用途、特征和其他方面的描述。

Product Life Cycle. 产品生命周期 代表一个产品从概念、交付、成长、成熟到衰退的整个演变过程的一系列阶段。

Product Scope. 产品范围 某项产品、服务或成果所具有的特征和功能。

Product Scope Description. 产品范围描述 对产品范围的书面叙述性描述。

Program. 项目集 相互关联且被协调管理的项目、子项目集和项目集活动,以便获得分别管理所无法获得的利益。

Program Management. 项目集管理 在项目集中应用知识、技能与原则来实现项目集的目标,获得分别管理项目集组成部分所无法实现的利益和控制。

Progressive Elaboration. 渐进明细 随着信息越来越多、估算越来越准确,而不断提高项目管理计划的详细程度的迭代过程。

Project. 项目 为创造独特的产品、服务或成果而进行的临时性工作。

Project Calendar. 项目日历 表明进度活动的可用工作日和工作班次的日历。

Project Charter. 项目章程 由项目启动者或发起人发布的,正式批准项目成立,并授权项目经理使用组织资源开展项目活动的文件。

Project Communications Management. 项目沟通管理 项目沟通管理包括为确保及时且恰当地规划、收集、生成、发布、存储、检索、管理、控制、监督和最终处置项目信息所需的各个过程。

Project Cost Management. 项目成本管理 项目成本管理包括为使项目在批准的预算内完成而对成本进行规划、估算、预算、融资、筹资、管理和控制的各个过程。

Project Funding Requirements. 项目资金需求 根据成本基准计算出的待付成本预测,可以是总量或阶段资金需求,包括预计支出加预计债务。

Project Governance. 项目治理 用于指导项目管理活动的框架、功能和过程,从而创造独特的产品、服务或结果以满足组织、战略和运营目标。

Project Initiation. 项目启动 发起一个用来正式授权新项目的过程。

Project Integration Management. 项目整合管理 项目整合管理包括对隶属于项目管理过程组的各种过程和项目管理活动进行识别、定义、组合、统一和协调的各个过程。

Project Life Cycle. 项目生命周期 项目从开始到结束所经历的一系列阶段。

Project Management. 项目管理 将知识、技能、工具与技术应用于项目活动,以满足项目的要求。

Project Management Body of Knowledge. 项目管理知识体系 描述项目管理专业范围内的知识的术语。项目管理知识体系包括已被验证并广泛应用的传统做法,以及本专业新近涌现的创新做法。

Project Management Information System. 项目管理信息系统 由收集、整合和传播项目管理过程成果的工具和技术所组成的信息系统。

Project Management Knowledge Area. 项目管理知识领域 按所需知识内容来定义的项目管理领域,并用其所含过程、做法、输入、输出、工具和技术进行描述。

Project Management Office (PMO). 项目管理办公室 对与项目相关的治理过程进行标准化,并促进资源、方法论、工具和技术共享的一种管理架构。

Project Management Plan. 项目管理计划 描述如何执行、监督、控制和结束项目的文件。

Project Management Process Group. 项目管理过程组 项目管理输入、工具和技术以及输出的逻辑组合。

项目管理过程组包括启动过程组、规划过程组、执行过程组、监控过程组和收尾过程组。项目管理过程组不同于项目阶段。

Project Management System. 项目管理系统 用于管理项目的各种过程、工具、技术、方法、资源和程序的集合。

Project Management Team. 项目管理团队 直接参与项目管理活动的项目团队成员。参见项目团队

Project Manager (PM). 项目经理 由执行组织委派,领导团队实现项目目标的个人。

Project Organization Chart. 项目组织图 以图形方式描述一个具体项目中项目团队成员及其相互关系的文件。

Project Phase. 项目阶段 一组具有逻辑关系的项目活动的集合,通常以一个或多个可交付成果的完成为结束。

Project Procurement Management. 项目采购管理 项目采购管理包括从项目团队外部采购或获取所需产品、服务或成果的各个过程。

Project Quality Management. 项目质量管理 项目质量管理包括把组织的质量政策应用于规划、管理、控制项目和产品质量要求,以满足相关方的期望的各个过程。

Project Resource Management. 项目资源管理 项目资源管理包括识别、获取和管理所需资源以成功完成项目的各个过程。

Project Risk Management. 项目风险管理 项目风险管理包括规划风险管理、识别风险、开展风险分析、规划风险应对、实施风险应对和监督风险的各个过程。

Project Schedule. 项目进度计划 进度模型的输出,为各个相互关联的活动标注了计划日期、持续时间、里程碑和资源等信息。

Project Schedule Management. 项目进度管理 项目进度管理包括为管理项目按时完成所需的各个过程。

Project Schedule Network Diagram. 项目进度网络图 表示项目进度活动之间逻辑关系的图形。

Project Scope. 项目范围 为交付具有规定特性与功能的产品、服务或成果而必须完成的工作。

Project Scope Management. 项目范围管理 项目范围管理包括确保项目做且只做所需的全部工作以成功完成项目的各个过程。

Project Scope Statement. 项目范围说明书 对项目范围、主要可交付成果、假设条件和制约因素的描述。

Project Stakeholder Management. 项目相关方管理 项目相关方管理包括用于开展下列工作的各个过程:识别能够影响项目或会受项目影响的人员、团体或组织,分析相关方对项目的期望和影响,制定合适的管理策略来有效调动相关方参与项目决策和执行。

Project Team. 项目团队 支持项目经理执行项目工作,以实现项目目标的一组人员。参见项目管理团队

Project Team Directory. 项目团队名录 列明项目团队成员及其项目角色和相关沟通信息的书面清单。

Proposal Evaluation Techniques. 建议书评价技术 为做出合同授予决定而用于评审供应商提交的建议书的各种技术。

Prototypes. 原型法 在实际制造预期产品之前,先造出其实用模型,并据此征求对需求的早期反馈的一种方法。

Quality. 质量 一系列内在特性满足要求的程度。

Quality Audits. 质量审计 质量审计是用于确定项目活动是否遵循了组织和项目的政策、过程与程序的一种结构化且独立的过程。

Quality Checklists. 质量核对单 用来核实所要求的一系列步骤是否已得到执行的结构化工具。

Quality Control Measurements. 质量控制测量结果 对质量控制活动的结果的书面记录。

Quality Management Plan. 质量管理计划 项目或项目集管理计划的组成部分,描述如何实施适用的政策、程序和指南以实现质量目标。

Quality Management System. 质量管理体系 为质量管理计划的实施提供政策、过程、程序和资源的组织架构。典型的项目质量管理计划应该与组织的质量管理体系相兼容。

Quality Metrics. 质量测量指标 对项目或产品属性及其测量方式的描述。

Quality Policy. 质量政策 项目质量管理知识领域中的专有政策,是组织在实施质量管理体系时必须遵守的基本原则。

Quality Report. 质量报告 用于报告质量管理问题、纠正措施建议以及在质量控制活动中所发现的其他情况的一种项目文件,其中也可以包括对过程、项目和产品改进的建议。

Quality Requirement. 质量要求 必须达到的条件或具备的能力,借此验证成果属性的可接受性和评估成果的质量一致性。

Questionnaires. 问卷调查 设计一系列书面问题,向众多受访者快速收集信息。

RACI Chart. RACI 矩阵 责任分配矩阵的一种常见类型,使用执行、负责、咨询和知情等词语来定义相关方在项目活动中的参与状态。

Regression Analysis. 回归分析 通过考察一系列输入变量及其对应的输出结果,建立数学或统计关系的一种分析技术。

Regulations. 法规 政府机构对产品、过程或服务的特征的要求,包括政府强制遵守的相关管理规定。

Request for Information (RFI). 信息邀请书 采购文件的一种,买方借此邀请潜在卖方就某种产品、服务或卖方能力提供相关信息。

Request for Proposal (RFP). 建议邀请书 采购文件的一种,用来向潜在卖方征求对产品或服务的建议书。在某些应用领域,其含义可能更狭窄或更具体。

Request for Quotation (RFQ). 报价邀请书 采购文件的一种,用来向潜在卖方征求对通用或标准产品或服务的报价。有时可用来代替建议邀请书。在某些应用领域,其含义可能更狭窄或更具体。

Requirement. 需求(要求) 为满足业务需求,某个产品、服务或成果必须达到的条件或具备的能力。

Requirements Documentation. 需求文件 关于各种单一需求将如何满足项目商业需求的描述。

Requirements Management Plan. 需求管理计划 项目或项目集管理计划的组成部分,描述将如何分析、记录和管理需求。

Requirements Traceability Matrix. 需求跟踪矩阵 把产品需求从其来源连接到能满足需求的可交付成果的一种表格。

Reserve. 储备 为减轻成本和/或进度风险,而在项目管理计划中所设的一种准备。使用时常加修饰词(如管理储备、应急储备),以进一步说明其用于减轻何种风险。

Reserve Analysis. 储备分析 一种分析技术,用来明确项目管理计划各组成部分的基本特征及其相互关系,从而为项目的工期、预算、成本估算或资金需求设定储备。

Residual Risk. 残余风险 采取风险应对措施之后仍然存在的风险。

Resource. 资源 完成项目所需的团队成员或任何实物。

Resource Breakdown Structure. 资源分解结构 资源依类别和类型的层级展现。

Resource Calendar. 资源日历 表明每种具体资源的可用工作日或工作班次的日历。

Resource Histogram. 资源直方图 按一系列时间段显示某种资源的计划工作时间的条形图。

Resource Leveling. 资源平衡 一种资源优化技术,对项目进度计划进行调整以优化资源分配,并可能会影响关键路径。参见资源优化技术资源平滑

Resource Management Plan. 资源管理计划 项目管理计划的一个组成部分,描述如何获取、分配、监督和控制项目资源。

Resource Manager. 资源经理 具有管理一项或多项资源权限的个人。

Resource Optimization Technique. 资源优化技术 根据资源的供求情况来调整活动开始和完成日期的一种技术。参见资源平衡资源平滑

Resource Requirements. 资源需求 工作包中的每个活动所需的资源类型和数量。

Resource Smoothing. 资源平滑 一种资源优化技术,在不影响关键路径的情况下使用自由浮动时间和总浮动时间。参见资源平衡资源优化技术

Responsibility. 职责 可在项目管理计划中进行委派的任务,接受委派的资源负有按要求完成任务的义务。

Responsibility Assignment Matrix (RAM). 责任分配矩阵 一种展示项目资源在各个工作包中的任务分配的表格。

Result. 成果 实施项目管理过程和活动所产生的输出。成果包括结果(如整合的系统、修订后的过程、重组后的组织、完成的测试、经培训的人员等)和文件(如政策、计划、研究报告、程序、规范、报告等)。参见可交付成果

Rework. 返工 为了使有缺陷或非一致的部件达到要求或符合规范而采取的行动。

Risk. 风险 一旦发生,会对一个或多个项目目标产生积极或消极影响的不确定事件或条件。

Risk Acceptance. 风险接受 一种风险应对策略,项目团队决定接受风险的存在,而不采取任何措施,除非风险真的发生。

Risk Appetite. 风险偏好 为了预期的回报,组织或个人愿意承担不确定性的程度。

Risk Audit. 风险审计 一种用于评价风险管理过程有效性的审计。

Risk Avoidance. 风险规避 一种风险应对策略,项目团队采取行动来消除威胁,或保护项目免受风险影响。

Risk Breakdown Structure (RBS). 风险分解结构 对潜在风险来源的一种层级图示。

Risk Categorization. 风险分类 按照风险来源(如使用风险分解结构)、受影响的项目区域(如使用工作分解结构),或其他有用的分类标准(如项目阶段),对项目风险进行分类,以明确受不确定性影响最大的项目区域。

Risk Category. 风险类别 对潜在风险成因的归组。

Risk Data Quality Assessment. 风险数据质量评估 评估风险数据对风险管理的有用程度的一种技术。

Risk Enhancement. 风险提高 一种风险应对策略,项目团队采取行动提升机会出现的概率或扩大机会造成的影响。

Risk Escalation. 风险上报 一种风险应对策略,即团队认为风险超出了自身可影响的范围,并将风险责任转移到组织中能更有效管理风险的更高层。

Risk Exploiting. 风险开拓 一种风险应对策略,项目团队采取行动以确保机会出现。

Risk Exposure. 风险敞口 在某个项目、项目集或项目组合中,针对任一特定对象,而适时作出的对所有风险的潜在影响的综合评估。

Risk Management Plan. 风险管理计划 项目、项目集或项目组合管理计划的组成部分,说明将如何安排与实施风险管理活动。

Risk Mitigation. 风险减轻 一种风险应对策略,项目团队采取行动以降低威胁发生的概率或削弱威胁造成的影响。

Risk Owner. 风险责任人 负责监测风险,选择并实施恰当的风险应对策略的个人。

Risk Register. 风险登记册 记录风险管理过程输出的文件。

Risk Report. 风险报告 在整个项目风险管理过程中不断更新的项目文件,用以概述单个项目风险的情况和整体项目风险的程度。

Risk Review. 风险审查 检查和记录应对整体项目风险和已识别单个项目风险的有效性的会议。

Risk Sharing. 风险分享 一种风险应对策略,项目团队将应对机会的责任分配给最能为项目获得利益的第三方。

Risk Threshold. 风险临界值 某种特定的风险敞口级别,高于该级别的风险需要处理,低于该级别的风险则可接受。

Risk Transference. 风险转移 一种风险应对策略,项目团队把威胁造成的影响连同应对责任一起转移给第三方。

Role. 角色 项目团队成员必须履行的、已明确定义的职责,如测试、归档、检查、编码等。

Rolling Wave Planning. 滚动式规划 一种迭代式的规划技术,对近期要完成的工作进行详细规划,对远期工作只做粗略规划。

Root Cause Analysis. 根本原因分析 确定引起偏差、缺陷或风险的根本原因的一种分析技术。一项根本原因可能引起多项偏差、缺陷或风险。

Schedule. 进度计划 参见项目进度进度模型

Schedule Baseline. 进度基准 经过批准的进度模型,能够通过正式的变更控制程序进行变更,并被用作与实际结果进行比较的依据。

Schedule Compression. 进度压缩 在不缩小项目范围的前提下缩短进度工期的技术。

Schedule Data. 进度数据 用以描述和控制进度计划的信息集合。

Schedule Forecasts. 进度预测 根据测算进度时已有的信息和知识,对项目未来的情况和事件所进行的估算或预计。

Schedule Management Plan. 进度管理计划 项目或项目集管理计划的组成部分,为编制、监督和控制项目进度建立准则并确定活动。

Schedule Model. 进度模型 项目活动执行计划的一种表现形式,其中包含持续时间、依赖关系和其他规划信息,用以生成项目进度计划及其他进度资料。

Schedule Network Analysis. 进度网络分析 识别项目活动未完部分的最早和最晚开始日期,以及最早和最晚完成日期的一种技术。

Schedule Performance Index (SPI). 进度绩效指数 测量进度效率的一种指标,表示为挣值与计划价值之比。

Schedule Variance (SV). 进度偏差 测量进度绩效的一种指标,表示为挣值与计划价值之差。

Scheduling Tool. 进度计划编制工具 配合进度计划编制方法使用的工具,可提供进度计划组成部分的名称、定义、结构关系和格式。

Scope. 范围 项目所提供的产品、服务和成果的总和。参见项目范围产品范围

Scope Baseline. 范围基准 经过批准的范围说明书、工作分解结构(WBS)和相应的 WBS 词典,能够通过正式的变更控制程序进行变更,并被用作与实际结果进行比较的依据。

Scope Creep. 范围蔓延 未对时间、成本和资源做相应调整,未经控制的产品或项目范围的扩大。

Scope Management Plan. 范围管理计划 项目或项目集管理计划的组成部分,描述将如何定义、制定、监督、控制和确认项目范围。

Secondary Risk. 次生风险 由于实施风险应对措施而直接产生的风险。

Self-Organizing Teams. 自组织团队 团队运作无需集中管控的一种团队形式。

Seller. 卖方 向某个组织提供产品、服务或成果的供应商。

Seller Proposals. 卖方建议书 卖方对建议邀请书或其他采购文件的正式应答,规定了价格、商务销售条款,以及技术规范或卖方将为买方建成的能力,一旦被接受,将形成有约束力的协议。

Sensitivity Analysis. 敏感性分析 一种定量风险分析技术,将项目结果的变化与定量风险分析模型中输入的的变化建立关联,从而确定对项目结果产生最大潜在影响的单个项目风险或其他不确定性来源。

Sequence Activities. 排列活动顺序 识别和记录项目活动之间的关系的过程。

Service Level Agreement (SLA). 服务水平协议 (SLA) 服务商(内部或外部)与最终用户之间的合同,用以规定服务商应该达到的服务水准。

Simulation. 模拟 一种分析技术,通过建立模型,来综合分析各种不确定性因素,评估这些因素对目标的,潜在影响。

Source Selection Criteria. 供方选择标准 买方提出的一套标准,卖方只有满足或超过这些标准,才有可能被授予合同。

Specification. 规范(规格) 对需要满足的需求和所需基本特征的准确表述。

Specification Limits. 规格界限 控制图中心线或均值两侧的数据区域,该区域内的数据都满足客户对产品或服务的要求。该区域可能大于或小于控制界限所界定的范围。参见控制界限

Sponsor. 发起人 为项目、项目集或项目组合提供资源和支持,并负责为成功创造条件的个人或团体。

Sponsoring Organization. 发起组织 负责提供项目发起人并为项目输送资金或其他资源的实体。

Stakeholder. 相关方 能影响项目、项目集或项目组合的决策、活动或结果的个人、小组或组织,以及会受或自认为会受它们的决策、活动或结果影响的个人、小组或组织。

Stakeholder Analysis. 相关方分析 通过系统收集和分析各种定量与定性信息,来确定在整个项目中应该考虑哪些人的利益的一种技术。

Stakeholder Engagement Assessment Matrix. 相关方参与度评估矩阵 将当前与期望的相关方参与程度进行比较的一种矩阵。

Stakeholder Engagement Plan. 相关方参与计划 项目管理计划的一个组成部分,为促进相关方有效参与项目或项目集决策和执行而规定所需的策略和行动。

Stakeholder Register. 相关方登记册 记录项目相关方识别、评估和分类结果的项目文件。

Standard. 标准 基于职权、惯例或共识而建立并用作模型或范例的文件。

Start Date. 开始日期 与进度活动的开始相关联的时间点。通常带下列修饰词:实际、计划、估计、预计、最早、最晚、目标、基准或当前。

Start-to-Finish (SF). 开始到完成 只有紧前活动开始,紧后活动才能完成的逻辑关系。

Start-to-Start (SS). 开始到开始 只有紧前活动开始,紧后活动才能开始的逻辑关系。

Statement of Work (SOW). 工作说明书 对项目需交付的产品、服务或成果的叙述性说明。

Statistical Sampling. 统计抽样 从目标总体中选取部分样本用于检查。

Successor Activity. 紧后活动 在进度计划的逻辑路径中,排在某个活动后面的活动。

Summary Activity. 概括性活动 作为单个活动来展示的,一组相关的进度活动的集合。

SWOT Analysis. SWOT 分析 对一个组织、项目或备选方案的优势、劣势、机会和威胁的分析。

Tacit Knowledge. 隐性知识 难以明确表达和分享的个人知识,如信念、经验和洞察力。

Tailoring. 裁剪 确定过程、输入、工具、技术、输出和生命周期阶段的恰当组合以管理项目。

Team Charter. 团队章程 记录团队价值观、共识和工作指南的文件,并对项目团队成员的可接受行为作出明确规定。

Team Management Plan. 团队管理计划 资源管理计划的组成部分,说明将在何时、以何种方式获得项目团队成员,以及他们需要在项目中工作多久。

Technique. 技术 人们在执行活动以生产产品、取得成果或提供服务的过程中所使用的经过定义的系统化程序,其中可能用到一种或多种工具。

Templates. 模板 一种固定格式的、已部分完成的文件,为收集、组织和呈现信息与数据提供明确的结构。

Test and Evaluation Documents. 测试与评估文件 描述用于确定产品是否达到质量管理计划中规定的质量目标的各种活动的项目文件。

Threat. 威胁 对项目的一个或多个目标产生负面影响的风险。

Three-Point Estimating. 三点估算 一种估算技术。当单个活动的成本或持续时间估算不易确定时,取其乐观估算、悲观估算和最可能估算的平均值或加权平均值。

Threshold. 临界值 针对可测量的项目变量而预先确定的一个限值,一旦达到此限值就需要采取相应行动。

Time and Material Contract (T&M). 工料合同 (T&M) 兼具成本补偿和总价合同特征的一种混合的合同类型。

To-Complete Performance Index (TCPI). 完工尚需绩效指数 为了实现特定的管理目标,剩余资源的使用必须达到的成本绩效指标,是完成剩余工作所需成本与剩余预算之比。

Tolerance. 公差 对质量要求可接受的变动范围的定量描述。

Tool. 工具 在创造产品或成果的活动中所使用的某种有形的东西,如模板或软件。

Tornado Diagram. 龙卷风图 在敏感性分析中用来比较不同变量的相对重要性的一种特殊形式的条形图。

Total Float. 总浮动时间 在不延误项目完成日期或违反进度制约因素的前提下,进度活动可以从其最早开始日期推迟或拖延的时间量。

Trend Analysis. 趋势分析 根据历史数据并利用数学模型,预测未来结果的一种分析技术。

Trigger Condition. 触发条件 表明风险即将发生的事件或情形。

Unanimity. 一致同意 对某个行动方案,小组中的每个人都表示同意。

Update. 更新 无需正式变更控制的,对任何可交付成果、项目管理计划组成部分或项目文件所作的修改。

Validate Scope. 确认范围 正式验收已完成的项目可交付成果的过程。

Validation. 确认 对产品、服务或成果能够满足客户和其他已识别相关方需求的保证。比较核实

Variance. 偏差 对已知基准或预期值的偏离量。

Variance Analysis. 偏差分析 确定实际绩效与基准的差异程度及原因的一种技术。

Variance At Completion (VAC). 完工偏差 对预算亏空量或盈余量的一种预测,是完工预算与完工估算之差。

Variation. 差异 不同于基准计划中规定的期望情况的实际情况。

Verification. 核实 关于产品、服务或成果是否符合法规、要求、规范或强制条件的评估。比较确认

Verified Deliverables. 核实的可交付成果 经过控制质量过程的检查,被证实为正确的已完成的可交付成果。

Virtual Teams. 虚拟团队 拥有共同目标的,在很少或不能见面的情况下,完成相应任务的一组人。

Voice of the Customer. 客户声音 一种规划技术,通过在项目产品开发的每个阶段把客户需求转变成适当的技术要求,来提供真正反映客户需求的产品、服务和成果。

WBS Dictionary. WBS词典 针对工作分解结构中的每个组件,详细描述可交付成果、活动和进度信息的文件。

What-If Scenario Analysis. 假设情景分析 对各种情景进行评估,预测它们对项目目标的影响的过程。

Work Breakdown Structure (WBS). 工作分解结构 对项目团队为实现项目目标、创建所需可交付成果而需要实施的全部工作范围的层级分解。

Work Breakdown Structure Component. 工作分解结构组件 工作分解结构任意层次上的任何要素。

Work Package. 工作包 工作分解结构最低层的工作,针对这些工作来估算并管理成本和持续时间。

Work Performance Data. 工作绩效数据 在执行项目工作的过程中,从每个正在执行的活动中收集到的原始观察结果和测量值。

Work Performance Information. 工作绩效信息 从控制过程中收集且与项目管理计划组成部分、项目文件进行对比分析的绩效数据,以及其他工作绩效信息。

Work Performance Reports. 工作绩效报告 为制定决策、采取行动或引起关注,而汇编工作绩效信息所形成的实物或电子项目文件。


.NET程序的性能要领和优化建议

本文提供了一些性能优化的建议,这些经验来自于使用托管代码重写C# 和 VB编译器,并以编写C# 编译器中的一些真实场景作为例子来展示这些优化经验。.NET 平台开发应用程序具有极高的生产力。.NET 平台上强大安全的编程语言以及丰富的类库,使得开发应用变得卓有成效。但是能力越大责任越大。我们应该使用.NET框架的强大能力,但同时如果我们需要处理大量的数据比如文件或者数据库也需要准备对我们的代码进行调优。

为什么来自新的编译器的性能优化经验也适用于您的应用程序

微软使用托管代码重写了C#和Visual Basic的编译器,并提供了一些列新的API来进行代码建模和分析、开发编译工具,使得Visual Studio具有更加丰富的代码感知的编程体验。重写编译器,并且在新的编译器上开发Visual Studio的经验使得我们获得了非常有用的性能优化经验,这些经验也能用于大型的.NET应用,或者一些需要处理大量数据的APP上。你不需要了解编译器,也能够从C#编译器的例子中得出这些见解。

Visual Studio使用了编译器的API来实现了强大的智能感知(Intellisense)功能,如代码关键字着色,语法填充列表,错误波浪线提示,参数提示,代码问题及修改建议等,这些功能深受开发者欢迎。Visual Studio在开发者输入或者修改代码的时候,会动态的编译代码来获得对代码的分析和提示。

当用户和App进行交互的时候,通常希望软件具有好的响应性。输入或者执行命令的时候,应用程序界面不应该被阻塞。帮助或者提示能够迅速显示出来或者当用户继续输入的时候停止提示。现在的App应该避免在执行长时间计算的时候阻塞UI线程从而让用户感觉程序不够流畅。

想了解更多关于新的编译器的信息,可以访问 .NET Compiler Platform ("Roslyn")

基本要领

在对.NET 进行性能调优以及开发具有良好响应性的应用程序的时候,请考虑以下这些基本要领:

要领一:不要过早优化

编写代码比想象中的要复杂的多,代码需要维护,调试及优化性能。 一个有经验的程序员,通常会对自然而然的提出解决问题的方法并编写高效的代码。 但是有时候也可能会陷入过早优化代码的问题中。比如,有时候使用一个简单的数组就够了,非要优化成使用哈希表,有时候简单的重新计算一下可以,非要使用复杂的可能导致内存泄漏的缓存。发现问题时,应该首先测试性能问题然后再分析代码。

要领二:没有评测,便是猜测

剖析和测量不会撒谎。测评可以显示CPU是否满负荷运转或者是存在磁盘I/O阻塞。测评会告诉你应用程序分配了什么样的以及多大的内存,以及是否CPU花费了很多时间在垃圾回收上。

应该为关键的用户体验或者场景设置性能目标,并且编写测试来测量性能。通过使用科学的方法来分析性能不达标的原因的步骤如下:使用测评报告来指导,假设可能出现的情况,并且编写实验代码或者修改代码来验证我们的假设或者修正。如果我们设置了基本的性能指标并且经常测试,就能够避免一些改变导致性能的回退(regression),这样就能够避免我们浪费时间在一些不必要的改动中。

要领三:好工具很重要

好的工具能够让我们能够快速的定位到影响性能的最大因素(CPU,内存,磁盘)并且能够帮助我们定位产生这些瓶颈的代码。微软已经发布了很多性能测试工具比如:Visual Studio ProfilerWindows Phone Analysis Tool, 以及 PerfView.

PerfView是一款免费且性能强大的工具,他主要关注影响性能的一些深层次的问题(磁盘 I/O,GC 事件,内存),后面会展示这方面的例子。我们能够抓取性能相关的 Event Tracing for Windows(ETW)事件并能以应用程序,进程,堆栈,线程的尺度查看这些信息。PerfView能够展示应用程序分配了多少,以及分配了何种内存以及应用程序中的函数以及调用堆栈对内存分配的贡献。这些方面的细节,您可以查看随工具下载发布的关于PerfView的非常详细的帮助,Demo以及视频教程(比如Channel9 上的视频教程)

要领四:所有的都与内存分配相关

你可能会想,编写响应及时的基于.NET的应用程序关键在于采用好的算法,比如使用快速排序替代冒泡排序,但是实际情况并不是这样。编写一个响应良好的app的最大因素在于内存分配,特别是当app非常大或者处理大量数据的时候。

在使用新的编译器API开发响应良好的IDE的实践中,大部分工作都花在了如何避免开辟内存以及管理缓存策略。PerfView追踪显示新的C# 和VB编译器的性能基本上和CPU的性能瓶颈没有关系。编译器在读入成百上千甚至上万行代码,读入元数据活着产生编译好的代码,这些操作其实都是I/O bound 密集型。UI线程的延迟几乎全部都是由于垃圾回收导致的。.NET框架对垃圾回收的性能已经进行过高度优化,他能够在应用程序代码执行的时候并行的执行垃圾回收的大部分操作。但是,单个内存分配操作有可能会触发一次昂贵的垃圾回收操作,这样GC会暂时挂起所有线程来进行垃圾回收(比如 Generation 2型的垃圾回收)

常见的内存分配以及例子

这部分的例子虽然背后关于内存分配的地方很少。但是,如果一个大的应用程序执行足够多的这些小的会导致内存分配的表达式,那么这些表达式会导致几百M,甚至几G的内存分配。比如,在性能测试团队把问题定位到输入场景之前,一分钟的测试模拟开发者在编译器里面编写代码会分配几G的内存。

装箱

装箱发生在当通常分配在线程栈上或者数据结构中的值类型,或者临时的值需要被包装到对象中的时候(比如分配一个对象来存放数据,活着返回一个指针给一个Object对象)。.NET框架由于方法的签名或者类型的分配位置,有些时候会自动对值类型进行装箱。将值类型包装为引用类型会产生内存分配。.NET框架及语言会尽量避免不必要的装箱,但是有时候在我们没有注意到的时候会产生装箱操作。过多的装箱操作会在应用程序中分配成M上G的内存,这就意味着垃圾回收的更加频繁,也会花更长时间。

在PerfView中查看装箱操作,只需要开启一个追踪(trace),然后查看应用程序名字下面的GC Heap Alloc 项(记住,PerfView会报告所有的进程的资源分配情况),如果在分配相中看到了一些诸如System.Int32和System.Char的值类型,那么就发生了装箱。选择一个类型,就会显示调用栈以及发生装箱的操作的函数。

例1 string方法和其值类型参数

下面的示例代码演示了潜在的不必要的装箱以及在大的系统中的频繁的装箱操作。

public class Logger
{
    public static void WriteLine(string s)
    {
        /*...*/
    }
}
public class BoxingExample
{
    public void Log(int id, int size)
    {
        var s = string.Format("{0}:{1}", id, size);
        Logger.WriteLine(s);
    }
}

这是一个日志基础类,因此app会很频繁的调用Log函数来记日志,可能该方法会被调用millons次。问题在于,调用string.Format方法会调用其重载的接受一个string类型和两个Object类型的方法:

String.Format Method (String, Object, Object)

该重载方法要求.NET Framework 把int型装箱为object类型然后将它传到方法调用中去。为了解决这一问题,方法就是调用id.ToString()size.ToString()方法,然后传入到string.Format 方法中去,调用ToString()方法的确会导致一个string的分配,但是在string.Format方法内部不论怎样都会产生string类型的分配。

你可能会认为这个基本的调用string.Format 仅仅是字符串的拼接,所以你可能会写出这样的代码:

var s = id.ToString() + ':' + size.ToString();

实际上,上面这行代码也会导致装箱,因为上面的语句在编译的时候会调用:

string.Concat(Object, Object, Object);

这个方法,.NET Framework 必须对字符常量进行装箱来调用Concat方法。

解决方法:

完全修复这个问题很简单,将上面的单引号替换为双引号即将字符常量换为字符串常量就可以避免装箱,因为string类型的已经是引用类型了。

var s = id.ToString() + ":" + size.ToString();

例2 枚举类型的装箱

下面的这个例子是导致新的C# 和VB编译器由于频繁的使用枚举类型,特别是在Dictionary中做查找操作时分配了大量内存的原因。

public enum Color { Red, Green, Blue }
public class BoxingExample
{
    private string name;
    private Color color;
    public override int GetHashCode()
    {
        return name.GetHashCode() ^ color.GetHashCode();
    }
}

问题非常隐蔽,PerfView会告诉你enmu.GetHashCode()由于内部实现的原因产生了装箱操作,该方法会在底层枚举类型的表现形式上进行装箱,如果仔细看PerfView,会看到每次调用GetHashCode会产生两次装箱操作。编译器插入一次,.NET Framework插入另外一次。

解决方法:

通过在调用GetHashCode的时候将枚举的底层表现形式进行强制类型转换就可以避免这一装箱操作。

((int)color).GetHashCode()

另一个使用枚举类型经常产生装箱的操作时enum.HasFlag。传给HasFlag的参数必须进行装箱,在大多数情况下,反复调用HasFlag通过位运算测试非常简单和不需要分配内存。

要牢记基本要领第一条,不要过早优化。并且不要过早的开始重写所有代码。 需要注意到这些装箱的耗费,只有在通过工具找到并且定位到最主要问题所在再开始修改代码。

字符串

字符串操作是引起内存分配的最大元凶之一,通常在PerfView中占到前五导致内存分配的原因。应用程序使用字符串来进行序列化,表示JSON和REST。在不支持枚举类型的情况下,字符串可以用来与其他系统进行交互。当我们定位到是由于string操作导致对性能产生严重影响的时候,需要留意string类的Format(),Concat(),Split(),Join(),Substring()等这些方法。使用StringBuilder能够避免在拼接多个字符串时创建多个新字符串的开销,但是StringBuilder的创建也需要进行良好的控制以避免可能会产生的性能瓶颈。

例3 字符串操作

在C#编译器中有如下方法来输出方法前面的xml格式的注释。

public void WriteFormattedDocComment(string text)
{
    string[] lines = text.Split(new[] {"\r\n", "\r", "\n"},
        StringSplitOptions.None);
    int numLines = lines.Length;
    bool skipSpace = true;
    if (lines[0].TrimStart().StartsWith("///"))
    {
        for (int i = 0; i < numLines; i++)
        {
            string trimmed = lines[i].TrimStart();
            if (trimmed.Length < 4 || !char.IsWhiteSpace(trimmed[3]))
            {
                skipSpace = false;
                break;
            }
        }
        int substringStart = skipSpace ? 4 : 3;
        for (int i = 0; i < numLines; i++)
            Console.WriteLine(lines[i].TrimStart().Substring(substringStart));
    }
    else
    {
        /* ... */
    }
}

可以看到,在这片代码中包含有很多字符串操作。代码中使用类库方法来将行分割为字符串,来去除空格,来检查参数text是否是XML文档格式的注释,然后从行中取出字符串处理。

WriteFormattedDocComment方法每次被调用时,第一行代码调用Split()就会分配三个元素的字符串数组。编译器也需要产生代码来分配这个数组。因为编译器并不知道,如果Splite()存储了这一数组,那么其他部分的代码有可能会改变这个数组,这样就会影响到后面对WriteFormattedDocComment方法的调用。每次调用Splite()方法也会为参数text分配一个string,然后在分配其他内存来执行splite操作。

WriteFormattedDocComment方法中调用了三次TrimStart()方法,在内存环中调用了两次,这些都是重复的工作和内存分配。更糟糕的是,TrimStart()的无参重载方法的签名如下:

namespace System
{ 
    public class String 
    { 
        public string TrimStart(params char[] trimChars);
    }
}

该方法签名意味着,每次对TrimStart()的调用都回分配一个空的数组以及返回一个string类型的结果。

最后,调用了一次Substring()方法,这个方法通常会导致在内存中分配新的字符串。

解决方法:

和前面的只需要小小的修改即可解决内存分配的问题不同。在这个例子中,我们需要从头看,查看问题然后采用不同的方法解决。比如,可以意识到WriteFormattedDocComment()方法的参数是一个字符串,它包含了方法中需要的所有信息,因此,代码只需要做更多的index操作,而不是分配那么多小的string片段。

下面的方法并没有完全解,但是可以看到如何使用类似的技巧来解决本例中存在的问题。C#编译器使用如下的方式来消除所有的额外内存分配。

private int IndexOfFirstNonWhiteSpaceChar(string text, int start)
{
    while (start < text.Length && char.IsWhiteSpace(text[start])) 
        start++;
    return start;
}

private bool TrimmedStringStartsWith(string text, int start, string prefix)
{
    start = IndexOfFirstNonWhiteSpaceChar(text, start); 
    int len = text.Length - start; 
    if (len < prefix.Length) return false;
    for (int i = 0; i < len; i++)
    {
        if (prefix[i] != text[start + i]) 
            return false;
    }
    return true;
}

WriteFormattedDocComment() 方法的第一个版本分配了一个数组,几个子字符串,一个trim后的子字符串,以及一个空的params数组。也检查了”///”。修改后的代码仅使用了index操作,没有任何额外的内存分配。它查找第一个非空格的字符串,然后逐个字符串比较来查看是否以”///”开头。和使用TrimStart()不同,修改后的代码使用IndexOfFirstNonWhiteSpaceChar方法来返回第一个非空格的开始位置,通过使用这种方法,可以移除WriteFormattedDocComment()方法中的所有额外内存分配。

例4 StringBuilder

本例中使用StringBuilder。下面的函数用来产生泛型类型的全名:

public class Example 
{ 
    // Constructs a name like "SomeType<T1, T2, T3>" 
    public string GenerateFullTypeName(string name, int arity) 
    { 
        StringBuilder sb = new StringBuilder();
        sb.Append(name);
        if (arity != 0)
        { 
            sb.Append("<");
            for (int i = 1; i < arity; i++)
            {
                sb.Append("T"); sb.Append(i.ToString()); sb.Append(", ");
            } 
            sb.Append("T"); sb.Append(i.ToString()); sb.Append(">");
        }
        return sb.ToString(); 
    }
}

注意力集中到StringBuilder实例的创建上来。代码中调用sb.ToString()会导致一次内存分配。在StringBuilder中的内部实现也会导致内部内存分配,但是我们如果想要获取到string类型的结果化,这些分配无法避免。

解决方法:

要解决StringBuilder对象的分配就使用缓存。即使缓存一个可能被随时丢弃的单个实例对象也能够显著的提高程序性能。下面是该函数的新的实现。除了下面两行代码,其他代码均相同

// Constructs a name like "Foo<T1, T2, T3>" 
public string GenerateFullTypeName(string name, int arity)
{
    StringBuilder sb = AcquireBuilder(); /* Use sb as before */ 
    return GetStringAndReleaseBuilder(sb);
}

关键部分在于新的 AcquireBuilder()GetStringAndReleaseBuilder()方法:

[ThreadStatic]
private static StringBuilder cachedStringBuilder;

private static StringBuilder AcquireBuilder()
{
    StringBuilder result = cachedStringBuilder;
    if (result == null)
    {
        return new StringBuilder();
    } 
    result.Clear(); 
    cachedStringBuilder = null; 
    return result;
}

private static string GetStringAndReleaseBuilder(StringBuilder sb)
{
    string result = sb.ToString(); 
    cachedStringBuilder = sb; 
    return result;
}

上面方法实现中使用了thread-static字段来缓存StringBuilder对象,这是由于新的编译器使用了多线程的原因。很可能会忘掉这个ThreadStatic声明。Thread-static字符为每个执行这部分的代码的线程保留一个唯一的实例。

如果已经有了一个实例,那么AcquireBuilder()方法直接返回该缓存的实例,在清空后,将该字段或者缓存设置为null。否则AcquireBuilder()创建一个新的实例并返回,然后将字段和cache设置为null 。

当我们对StringBuilder处理完成之后,调用GetStringAndReleaseBuilder()方法即可获取string结果。然后将StringBuilder保存到字段中或者缓存起来,然后返回结果。这段代码很可能重复执行,从而创建多个StringBuilder对象,虽然很少会发生。代码中仅保存最后被释放的那个StringBuilder对象来留作后用。新的编译器中,这种简单的的缓存策略极大地减少了不必要的内存分配。.NET Framework 和MSBuild 中的部分模块也使用了类似的技术来提升性能。

简单的缓存策略必须遵循良好的缓存设计,因为他有大小的限制cap。使用缓存可能比之前有更多的代码,也需要更多的维护工作。我们只有在发现这是个问题之后才应该采缓存策略。PerfView已经显示出StringBuilder对内存的分配贡献相当大。

LINQ和Lambdas表达式

使用LINQ 和Lambdas表达式是C#语言强大生产力的一个很好体现,但是如果代码需要执行很多次的时候,可能需要对LINQ或者Lambdas表达式进行重写。

例5 Lambdas表达式,List<T>,以及IEnumerable<T>

下面的例子使用LINQ以及函数式风格的代码来通过编译器模型给定的名称来查找符号。

class Symbol 
{ 
    public string Name { get; private set; } /*...*/
}
class Compiler 
{ 
    private List<Symbol> symbols; 
    public Symbol FindMatchingSymbol(string name) 
    { 
        return symbols.FirstOrDefault(s => s.Name == name); 
    }
}

新的编译器和IDE 体验基于调用FindMatchingSymbol,这个调用非常频繁,在此过程中,这么简单的一行代码隐藏了基础内存分配开销。为了展示这其中的分配,我们首先将该单行函数拆分为两行:

Func<Symbol, bool> predicate = s => s.Name == name; 
return symbols.FirstOrDefault(predicate);

第一行中,lambda表达式 “s=>s.Name==name” 是对本地变量name的一个闭包。这就意味着需要分配额外的对象来为委托对象predict分配空间,需要一个分配一个静态类来保存环境从而保存name的值。编译器会产生如下代码:

// Compiler-generated class to hold environment state for lambda 
private class Lambda1Environment 
{ 
    public string capturedName; 
    public bool Evaluate(Symbol s) 
    { 
        return s.Name == this.capturedName;
    } 
}

// Expanded Func<Symbol, bool> predicate = s => s.Name == name; 
Lambda1Environment l = new Lambda1Environment() 
{ 
    capturedName = name
}; 
var predicate = new Func<Symbol, bool>(l.Evaluate);

两个new操作符(第一个创建一个环境类,第二个用来创建委托)很明显的表明了内存分配的情况。

现在来看看FirstOrDefault方法的调用,他是IEnumerable<T>类的扩展方法,这也会产生一次内存分配。因为FirstOrDefault使用IEnumerable<T>作为第一个参数,可以将上面的展开为下面的代码:

// Expanded return symbols.FirstOrDefault(predicate) ... 
IEnumerable<Symbol> enumerable = symbols;
IEnumerator<Symbol> enumerator = enumerable.GetEnumerator(); 
while (enumerator.MoveNext())
{ 
    if (predicate(enumerator.Current)) 
        return enumerator.Current; 
} 
return default(Symbol);

symbols变量是类型为List<T>的变量。List<T>集合类型实现了IEnumerable<T>即可并且清晰地定义了一个迭代器List<T>的迭代器使用了一种结构体来实现。使用结构而不是类意味着通常可以避免任何在托管堆上的分配,从而可以影响垃圾回收的效率。枚举典型的用处在于方便语言层面上使用foreach循环,他使用enumerator结构体在调用推栈上返回。递增调用堆栈指针来为对象分配空间,不会影响GC对托管对象的操作。

在上面的展开FirstOrDefault调用的例子中,代码会调用IEnumerabole<T>接口中的GetEnumerator()方法。将symbols赋值给IEnumerable<Symbol>类型的enumerable 变量,会使得对象丢失了其实际的List<T>类型信息。这就意味着当代码通过enumerable.GetEnumerator()方法获取迭代器时,.NET Framework 必须对返回的值(即迭代器,使用结构体实现)类型进行装箱从而将其赋给IEnumerable<Symbol>类型的(引用类型) enumerator变量。

解决方法:

解决办法是重写FindMatchingSymbol方法,将单个语句使用六行代码替代,这些代码依旧连贯,易于阅读和理解,也很容易实现。

public Symbol FindMatchingSymbol(string name) 
{ 
    foreach (Symbol s in symbols)
    { 
        if (s.Name == name) 
            return s; 
    } 
    return null; 
}

代码中并没有使用LINQ扩展方法,lambdas表达式和迭代器,并且没有额外的内存分配开销。这是因为编译器看到symbol 是List<T>类型的集合,因为能够直接将返回的结构性的枚举器绑定到类型正确的本地变量上,从而避免了对struct类型的装箱操作。原先的代码展示了C#语言丰富的表现形式以及.NET Framework 强大的生产力。该着后的代码则更加高效简单,并没有添加复杂的代码而增加可维护性。

Aync异步

接下来的例子展示了当我们试图缓存一部方法返回值时的一个普遍问题:

例6 缓存异步方法

Visual Studio IDE 的特性在很大程度上建立在新的C#和VB编译器获取语法树的基础上,当编译器使用async的时候仍能够保持Visual Stuido能够响应。下面是获取语法树的第一个版本的代码:

class Parser 
{
    /*...*/ 
    public SyntaxTree Syntax
    { 
        get; 
    } 
    
    public Task ParseSourceCode() 
    {
        /*...*/ 
    } 
}
class Compilation 
{ 
    /*...*/ 
    public async Task<SyntaxTree> GetSyntaxTreeAsync() 
    { 
        var parser = new Parser(); // allocation 
        await parser.ParseSourceCode(); // expensive 
        return parser.Syntax;
    } 
}

可以看到调用GetSyntaxTreeAsync() 方法会实例化一个Parser对象,解析代码,然后返回一个Task<SyntaxTree>对象。最耗性能的地方在为Parser实例分配内存并解析代码。方法中返回一个Task对象,因此调用者可以await解析工作,然后释放UI线程使得可以响应用户的输入。

由于Visual Studio的一些特性可能需要多次获取相同的语法树, 所以通常可能会缓存解析结果来节省时间和内存分配,但是下面的代码可能会导致内存分配:

class Compilation 
{ /*...*/
    private SyntaxTree cachedResult;
    public async Task<SyntaxTree> GetSyntaxTreeAsync() 
    { 
        if (this.cachedResult == null) 
        { 
            var parser = new Parser(); // allocation 
            await parser.ParseSourceCode(); // expensive 
            this.cachedResult = parser.Syntax; 
        } 
        return this.cachedResult;
    }
}

代码中有一个SynataxTree类型的名为cachedResult的字段。当该字段为空的时候,GetSyntaxTreeAsync()执行,然后将结果保存在cache中。GetSyntaxTreeAsync()方法返回SyntaxTree对象。问题在于,当有一个类型为Task<SyntaxTree> 类型的async异步方法时,想要返回SyntaxTree的值,编译器会生出代码来分配一个Task来保存执行结果(通过使用Task<SyntaxTree>.FromResult())。Task会标记为完成,然后结果立马返回。分配Task对象来存储执行的结果这个动作调用非常频繁,因此修复该分配问题能够极大提高应用程序响应性。

解决方法:

要移除保存完成了执行任务的分配,可以缓存Task对象来保存完成的结果。

class Compilation 
{ /*...*/
    private Task<SyntaxTree> cachedResult;
    public Task<SyntaxTree> GetSyntaxTreeAsync() 
    { 
        return this.cachedResult ?? (this.cachedResult = GetSyntaxTreeUncachedAsync()); 
    }
    private async Task<SyntaxTree> GetSyntaxTreeUncachedAsync() 
    {
        var parser = new Parser(); // allocation 
        await parser.ParseSourceCode(); // expensive 
        return parser.Syntax; 
    } 
}

代码将cachedResult 类型改为了Task<SyntaxTree> 并且引入了async帮助函数来保存原始代码中的GetSyntaxTreeAsync()函数。GetSyntaxTreeAsync函数现在使用 null操作符,来表示当cachedResult不为空时直接返回,为空时GetSyntaxTreeAsync调用GetSyntaxTreeUncachedAsync()然后缓存结果。注意GetSyntaxTreeAsync并没有await调用GetSyntaxTreeUncachedAsync。没有使用await意味着当GetSyntaxTreeUncachedAsync返回Task类型时,GetSyntaxTreeAsync 也立即返回Task, 现在缓存的是Task,因此在返回缓存结果的时候没有额外的内存分配。

其他一些影响性能的杂项

在大的app或者处理大量数据的app中,还有几点可能会引发潜在的性能问题。

字典

在很多应用程序中,Dictionary用的很广,虽然字非常方便和高校,但是经常会使用不当。在Visual Studio以及新的编译器中,使用性能分析工具发现,许多dictionay只包含有一个元素或者干脆是空的。一个空的Dictionay结构内部会有10个字段在x86机器上的托管堆上会占据48个字节。当需要在做映射或者关联数据结构需要事先常量时间查找的时候,字典非常有用。但是当只有几个元素,使用字典就会浪费大量内存空间。相反,我们可以使用List<KeyValuePair<K,V>>结构来实现便利,对于少量元素来说,同样高校。如果仅仅使用字典来加载数据,然后读取数据,那么使用一个具有N(log(N))的查找效率的有序数组,在速度上也会很快,当然这些都取决于的元素的个数。

类和结构

不甚严格的讲,在优化应用程序方面,类和结构提供了一种经典的空间/时间的权衡(trade off)。在x86机器上,每个类即使没有任何字段,也会分配12 byte的空间 (译注:来保存类型对象指针和同步索引块),但是将类作为方法之间参数传递的时候却十分高效廉价,因为只需要传递指向类型实例的指针即可。结构体如果不撞向的话,不会再托管堆上产生任何内存分配,但是当将一个比较大的结构体作为方法参数或者返回值得时候,需要CPU时间来自动复制和拷贝结构体,然后将结构体的属性缓存到本地便两种以避免过多的数据拷贝。

缓存

性能优化的一个常用技巧是缓存结果。但是如果缓存没有大小上限或者良好的资源释放机制就会导致内存泄漏。在处理大数据量的时候,如果在缓存中缓存了过多数据就会占用大量内存,这样导致的垃圾回收开销就会超过在缓存中查找结果所带来的好处。

结论

在大的系统,或者或者需要处理大量数据的系统中,我们需要关注产生性能瓶颈症状,这些问题再规模上会影响app的响应性,如装箱操作、字符串操作、LINQ和Lambda表达式、缓存async方法、缓存缺少大小限制以及良好的资源释放策略、使用Dictionay不当、以及到处传递结构体等。在优化我们的应用程序的时候,需要时刻注意之前提到过的四点:

  1. 不要进行过早优化——在定位和发现问题之后再进行调优。

  2. 专业测试不会说谎——没有评测,便是猜测。

  3. 好工具很重要。——下载PerfView,然后去看使用教程。

  4. 内存分配决定app的响应性。——这也是新的编译器性能团队花的时间最多的地方。

参考资料

C#基础知识之事件和委托

本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、委托的调用方式、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。

一、委托是什么

来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语:

public void GreetPeople(string name)

{

  EnglishGreeting(name);

}

public void EnglishGreeting(string name)

{

   Console.WriteLine("Morning, " + name);

}

现在假设这个程序需要进行全球化,哎呀,不好了,我是中国人,我不明白“Morning”是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法:

1

2

3

4

public void ChineseGreeting(string name)

{

   Console.WriteLine("早上好, " + name);

}

这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据:

public enum Language

{

   English, Chinese

}

public void GreetPeople(string name, Language lang)

  swith(lang){

     case Language.English:

      EnglishGreeting(name);

      break;

    case Language.Chinese:

      ChineseGreeting(name);

      break;

   }

}

这个解决方案的可扩展性很差,如果日后我们需要再添加韩文版、日文版,就不得不反复修改枚举和GreetPeople()方法,以适应新的需求。

在考虑新的解决方案之前,我们先看看 GreetPeople的方法签名:

1

public void GreetPeople(string name,   Language lang)

如果你再仔细想想,假如GreetPeople()方法可以接受一个参数变量,这个变量可以代表另一个方法,当我们给这个变量赋值 EnglishGreeting的时候,它代表着 EnglsihGreeting() 这个方法;当我们给它赋值ChineseGreeting 的时候,它又代表着ChineseGreeting()方法。我们将这个参数变量命名为 MakeGreeting,那么不是可以如同给name赋值时一样,在调用 GreetPeople()方法的时候,给这个MakeGreeting 参数也赋上值么(ChineseGreeting或者EnglsihGreeting等)?然后,我们在方法体内,也可以像使用别的参数一样使用MakeGreeting。好了,有了思路了,我们现在就来改改GreetPeople()方法,那么它应该是这个样子了:

1

public void GreetPeople(string name, ***   MakeGreeting) {    MakeGreeting(name); }

注意到 *** ,这个位置通常放置的应该是参数的类型,但到目前为止,我们仅仅是想到应该有个可以代表方法的参数,并按这个思路去改写GreetPeople方法,现在就出现了一个大问题:这个代表着方法的MakeGreeting参数应该是什么类型的?

聪明的你应该已经想到了,现在是委托该出场的时候了,但讲述委托之前,我们再看看MakeGreeting参数所能代表的 ChineseGreeting()和EnglishGreeting()方法的签名:

1

public void EnglishGreeting(string name) public void ChineseGreeting(string name)  

MakeGreeting的 参数类型定义 应该能够确定 MakeGreeting可以代表的方法种类,于是,委托出现了:它定义了MakeGreeting参数所能代表的方法的种类,也就是MakeGreeting参数的类型。

本例中委托的定义:

1

public delegate void GreetingDelegate(string name);

可以与上面EnglishGreeting()方法的签名对比一下,除了加入了delegate关键字以外,其余的是不是完全一样?

现在,让我们再次改动GreetPeople()方法,如下所示:

1

public void GreetPeople(string name,   GreetingDelegate MakeGreeting) {    MakeGreeting(name); }

如你所见,委托GreetingDelegate出现的位置与 string相同,string是一个类型,那么GreetingDelegate应该也是一个类型,或者叫类(Class)。但是委托的声明方式和类却完全不同,这是怎么一回事?实际上,委托在编译的时候确实会编译成类。因为Delegate是一个类,所以在任何可以声明类的地方都可以声明委托。看看这个范例的完整代码:

using System;

 using System.Collections.Generic;

 using System.Text;

 

 namespace Delegate {

   public delegate void GreetingDelegate(string name);

     class Program {

      private static void EnglishGreeting(string name) {

        Console.WriteLine("Morning, " + name);

      }

 

      private static void ChineseGreeting(string name) {

        Console.WriteLine("早上好, " + name);

      }

 

      //注意此方法,它接受一个GreetingDelegate类型的方法作为参数

      private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {

        MakeGreeting(name);

       }

 

      static void Main(string[] args) {

        GreetPeople("Jimmy Zhang", EnglishGreeting);

        GreetPeople("张子阳", ChineseGreeting);

        Console.ReadKey();

      }

     }

   }

输出如下:

Morning, Jimmy Zhang

早上好, 张子阳

我们现在对委托做一个总结:

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

二、委托的多播

委托可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。在这个例子中,语法如下:

static void Main(string[] args) {

   GreetingDelegate delegate1;

   delegate1 = EnglishGreeting; // 先给委托类型的变量赋值

   delegate1 += ChineseGreeting;  // 给此委托变量再绑定一个方法

   // 将先后调用 EnglishGreeting ChineseGreeting 方法

   delegate1 ("Jimmy Zhang"); 

   Console.ReadKey();

}

NOTE:第一次用的“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。我们也可以使用下面的代码来这样简化这一过程:

1

2

GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);

delegate1 += ChineseGreeting;   // 给此委托变量再绑定一个方法

看到这里,应该注意到,这段代码第一条语句与实例化一个类是何其的相似,你不禁想到:上面第一次绑定委托时不可以使用“+=”的编译错误,或许可以用这样的方法来避免:代码如下:

1

2

3

GreetingDelegate delegate1 = new GreetingDelegate();

delegate1 += EnglishGreeting;   // 这次用的是 “+=”,绑定语法。

delegate1 += ChineseGreeting;   // 给此委托变量再绑定一个方法

但实际上,这样会出现编译错误: “GreetingDelegate”方法没有采用“0”个参数的重载。尽管这样的结果让我们觉得有点沮丧,但是编译的提示:“没有0个参数的重载”再次让我们联想到了类的构造函数。我知道你一定按捺不住想探个究竟,但再此之前我们需要先把基础知识和应用介绍完。既然给委托可以绑定一个方法,那么也应该有办法取消对方法的绑定,很容易想到,这个语法是“-=”:

static void Main(string[] args) {

   GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);

   delegate1 += ChineseGreeting;  // 给此委托变量再绑定一个方法

 

  // 将先后调用 EnglishGreeting ChineseGreeting 方法

   GreetPeople("Jimmy Zhang", delegate1);

   Console.WriteLine();

 

   delegate1 -= EnglishGreeting; //取消对EnglishGreeting方法的绑定

  // 将仅调用 ChineseGreeting

  GreetPeople("张子阳", delegate1);

  Console.ReadKey();

}

输出为:

Morning, Jimmy Zhang

早上好, Jimmy Zhang

早上好, 张子阳

 

三、事件的由来

我们继续思考上面的程序:上面的三个方法都定义在Program类中,这样做是为了理解的方便,实际应用中,通常都是 GreetPeople 在一个类中,ChineseGreeting和 EnglishGreeting 在另外的类中。现在你已经对委托有了初步了解,是时候对上面的例子做个改进了。假设我们将GreetingPeople()放在一个叫GreetingManager的类中,那么新程序应该是这个样子的:

namespace Delegate {

   //定义委托,它定义了可以代表的方法的类型

  public delegate void GreetingDelegate(string name);   

   //新建的GreetingManager

  public class GreetingManager{

    public void GreetPeople(string name, GreetingDelegate MakeGreeting) {

      MakeGreeting(name);

    }

   }

 

   class Program {

    private static void EnglishGreeting(string name) {

      Console.WriteLine("Morning, " + name);

    }

 

    private static void ChineseGreeting(string name) {

      Console.WriteLine("早上好, " + name);

    }

 

    static void Main(string[] args) {

       GreetingManager gm = new GreetingManager();

       gm.GreetPeople("Jimmy Zhang", EnglishGreeting);

       gm.GreetPeople("张子阳", ChineseGreeting);

     }

   }

}

 输出结果:

  Morning, Jimmy Zhang

  早上好, 张子阳

现在,假设我们需要使用上一节学到的知识,将多个方法绑定到同一个委托变量,该如何做呢?让我们再次改写代码:

static void Main(string[] args) {

   GreetingManager gm = new GreetingManager();

   GreetingDelegate delegate1;

   delegate1 = EnglishGreeting;

   delegate1 += ChineseGreeting;

   gm.GreetPeople("Jimmy Zhang", delegate1);

 }

输出:

Morning, Jimmy Zhang

早上好, Jimmy Zhang

到了这里,我们不禁想到:面向对象设计,讲究的是对象的封装,既然可以声明委托类型的变量,我们何不将这个变量封装到 GreetManager类中?在这个类的客户端中使用不是更方便么?于是,我们改写GreetManager类,像这样:

public class GreetingManager{

   //GreetingManager类的内部声明delegate1变量

  public GreetingDelegate delegate1; 

   public void GreetPeople(string name, GreetingDelegate MakeGreeting) {

    MakeGreeting(name);

   }

 }

现在,我们可以这样使用这个委托变量:

static void Main(string[] args) {

   GreetingManager gm = new GreetingManager();

   gm.delegate1 = EnglishGreeting;

   gm.delegate1 += ChineseGreeting;

   gm.GreetPeople("Jimmy Zhang", gm.delegate1);

 }

 

输出为:

Morning, Jimmy Zhang

早上好, Jimmy Zhang

尽管这样做没有任何问题,但我们发现这条语句很奇怪。在调用gm.GreetPeople方法的时候,再次传递了gm的delegate1字段。既然如此,我们何不修改 GreetingManager 类成这样:

public class GreetingManager{

   //GreetingManager类的内部声明delegate1变量

   public GreetingDelegate delegate1;

 

   public void GreetPeople(string name) {

     if(delegate1!=null){   //如果有方法注册委托变量

     delegate1(name);   //通过委托调用方法

    }

   }

 }

在客户端,调用看上去更简洁一些:

static void Main(string[] args) {

   GreetingManager gm = new GreetingManager();

   gm.delegate1 = EnglishGreeting;

   gm.delegate1 += ChineseGreeting;

 

   gm.GreetPeople("Jimmy Zhang");   //注意,这次不需要再传递 delegate1变量

}

 

输出为:

Morning, Jimmy Zhang

早上好, Jimmy Zhang

尽管这样达到了我们要的效果,但是还是存在着问题:

在这里,delegate1和我们平时用的string类型的变量没有什么分别,而我们知道,并不是所有的字段都应该声明成public,合适的做法是应该public的时候public,应该private的时候private。

我们先看看如果把 delegate1 声明为 private会怎样?结果就是:这简直就是在搞笑。因为声明委托的目的就是为了把它暴露在类的客户端进行方法的注册,你把它声明为private了,客户端对它根本就不可见,那它还有什么用?

再看看把delegate1 声明为 public 会怎样?结果就是:在客户端可以对它进行随意的赋值等操作,严重破坏对象的封装性。

最后,第一个方法注册用“=”,是赋值语法,因为要进行实例化,第二个方法注册则用的是“+=”。但是,不管是赋值还是注册,都是将方法绑定到委托上,除了调用时先后顺序不同,再没有任何的分别,这样不是让人觉得很别扭么?

于是,Event出场了,它封装了委托类型的变量,使得:在类的内部,不管你声明它是public还是protected,它总是private的。在类的外部,注册“+=”和注销“-=”的访问限定符与你在声明事件时使用的访问符相同。

我们改写GreetingManager类,它变成了这个样子:

public class GreetingManager{

   //这一次我们在这里声明一个事件

   public event GreetingDelegate MakeGreet;

 

   public void GreetPeople(string name) {

     MakeGreet(name);

   }

 }

很容易注意到:MakeGreet 事件的声明与之前委托变量delegate1的声明唯一的区别是多了一个event关键字。看到这里,在结合上面的讲解,你应该明白到:事件其实没什么不好理解的,声明一个事件不过类似于声明一个进行了封装的委托类型的变量而已。

为了证明上面的推论,如果我们像下面这样改写Main方法:

static void Main(string[] args) {

   GreetingManager gm = new GreetingManager();

   gm.MakeGreet = EnglishGreeting;     // 编译错误1

   gm.MakeGreet += ChineseGreeting;

   gm.GreetPeople("Jimmy Zhang");

 }

会得到编译错误:事件“Delegate.GreetingManager.MakeGreet”只能出现在 += 或 -= 的左边(从类型“Delegate.GreetingManager”中使用时除外)。

事件和委托的编译代码

这时候,我们注释掉编译错误的行,然后重新进行编译,再借助Reflactor来对 event的声明语句做一探究,看看为什么会发生这样的错误:

public event GreetingDelegate MakeGreet;

 

 可以看到,实际上尽管我们在GreetingManager里将 MakeGreet 声明为public,但是,实际上MakeGreet会被编译成 私有字段,难怪会发生上面的编译错误了,因为它根本就不允许在GreetingManager类的外面以赋值的方式访问,从而验证了我们上面所做的推论。

我们再进一步看下MakeGreet所产生的代码:

private GreetingDelegate MakeGreet; //对事件的声明 实际是 声明一个私有的委托变量

[MethodImpl(MethodImplOptions.Synchronized)]

public void add_MakeGreet(GreetingDelegate value){

   this.MakeGreet = (GreetingDelegate) Delegate.Combine(this.MakeGreet, value);

}

[MethodImpl(MethodImplOptions.Synchronized)]

public void remove_MakeGreet(GreetingDelegate value){

   this.MakeGreet = (GreetingDelegate) Delegate.Remove(this.MakeGreet, value);

}

现在已经很明确了:MakeGreet事件确实是一个GreetingDelegate类型的委托,只不过不管是不是声明为public,它总是被声明为private。另外,它还有两个方法,分别是add_MakeGreet和remove_MakeGreet,这两个方法分别用于注册委托类型的方法和取消注册。实际上也就是: “+= ”对应 add_MakeGreet,“-=”对应remove_MakeGreet。而这两个方法的访问限制取决于声明事件时的访问限制符。

在add_MakeGreet()方法内部,实际上调用了System.Delegate的Combine()静态方法,这个方法用于将当前的变量添加到委托链表中。我们前面提到过两次,说委托实际上是一个类,在我们定义委托的时候:

public delegate void GreetingDelegate(string name);

当编译器遇到这段代码的时候,会生成下面这样一个完整的类:

public sealed class GreetingDelegate:System.MulticastDelegate{

   public GreetingDelegate(object @object, IntPtr method);

   public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object);

   public virtual void EndInvoke(IAsyncResult result);

   public virtual void Invoke(string name);

 }

 

关于这个类的更深入内容,可以参阅《CLR Via C#》等相关书籍,这里就不再讨论了。

四、委托、事件与Observer设计模式

假设我们有个高档的热水器,我们给它通上电,当水温超过95度的时候:1、扬声器会开始发出语音,告诉你水的温度;2、液晶屏也会改变水温的显示,来提示水已经快烧开了。

现在我们需要写个程序来模拟这个烧水的过程,我们将定义一个类来代表热水器,我们管它叫:Heater,它有代表水温的字段,叫做temperature;当然,还有必不可少的给水加热方法BoilWater(),一个发出语音警报的方法MakeAlert(),一个显示水温的方法,ShowMsg()。

namespace Delegate {

   class Heater {

   private int temperature; // 水温

   // 烧水

   public void BoilWater() {

     for (int i = 0; i <= 100; i++) {

      temperature = i;

 

      if (temperature > 95) {

        MakeAlert(temperature);

        ShowMsg(temperature);

       }

     }

   }

 

   // 发出语音警报

  private void MakeAlert(int param) {

    Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:" , param);

   }

   

   // 显示水温

  private void ShowMsg(int param) {

    Console.WriteLine("Display:水快开了,当前温度:{0}度。" , param);

   }

 }

 

class Program {

   static void Main() {

    Heater ht = new Heater();

    ht.BoilWater();

   }

 }

}

Observer设计模式简介

上面的例子显然能完成我们之前描述的工作,但是却并不够好。现在假设热水器由三部分组成:热水器、警报器、显示器,它们来自于不同厂商并进行了组装。那么,应该是热水器仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由警报器发出警报、显示器显示提示和水温。这时候,上面的例子就应该变成这个样子:

// 热水器

public class Heater {

   private int temperature;

     

   // 烧水

   private void BoilWater() {

    for (int i = 0; i <= 100; i++) {

      temperature = i;

     }

   }

}

 

// 警报器

public class Alarm{

   private void MakeAlert(int param) {

    Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:" , param);

   }

}

 

// 显示器

public class Display{

   private void ShowMsg(int param) {

    Console.WriteLine("Display:水已烧开,当前温度:{0}度。" , param);

   }

}

这里就出现了一个问题:如何在水烧开的时候通知报警器和显示器?在继续进行之前,我们先了解一下Observer设计模式,Observer设计模式中主要包括如下两类对象:

1.Subject:监视对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个监视对象,它包含的其他对象所感兴趣的内容,就是temprature字段,当这个字段的值快到100时,会不断把数据发给监视它的对象。

2.Observer:监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器和显示器,它们采取的行动分别是发出警报和显示水温。

在本例中,事情发生的顺序应该是这样的:

1.警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。

2.热水器知道后保留对警报器和显示器的引用。

3.热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。

类似这样的例子是很多的,GOF对它进行了抽象,称为Observer设计模式:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。

实现范例的Observer设计模式

我们之前已经对委托和事件介绍很多了,现在写代码应该很容易了,现在在这里直接给出代码,并在注释中加以说明。

using System;

using System.Collections.Generic;

using System.Text;

 

namespace Delegate {

   // 热水器

  public class Heater {

     private int temperature;

     public delegate void BoilHandler(int param);  //声明委托

    public event BoilHandler BoilEvent;    //声明事件

 

    // 烧水

    public void BoilWater() {

      for (int i = 0; i <= 100; i++) {

        temperature = i;

        if (temperature > 95) {

          if (BoilEvent != null) { //如果有对象注册

           BoilEvent(temperature); //调用所有注册对象的方法

         }

        }

      }

    }

   }

 

   // 警报器

  public class Alarm {

    public void MakeAlert(int param) {

      Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);

    }

   }

 

   // 显示器

  public class Display {

    public static void ShowMsg(int param) { //静态方法

      Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", param);

    }

   }

   

   class Program {

    static void Main() {

      Heater heater = new Heater();

      Alarm alarm = new Alarm();

 

      heater.BoilEvent += alarm.MakeAlert;  //注册方法

      heater.BoilEvent += (new Alarm()).MakeAlert;  //给匿名对象注册方法

      heater.BoilEvent += Display.ShowMsg;    //注册静态方法

      heater.BoilWater();  //烧水,会自动调用注册过对象的方法

    }

   }

 }

输出为:

Alarm:嘀嘀嘀,水已经 96 度了:

Alarm:嘀嘀嘀,水已经 96 度了:

Display:水快烧开了,当前温度:96度。

// 省略...

 

五、.Net Framework中的委托与事件

尽管上面的范例很好地完成了我们想要完成的工作,但是我们不仅疑惑:为什么.Net Framework 中的事件模型和上面的不同?为什么有很多的EventArgs参数?

在回答上面的问题之前,我们先搞懂 .Net Framework的编码规范:

·         委托类型的名称都应该以EventHandler结束。

·         委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。

·         事件的命名为 委托去掉 EventHandler之后剩余的部分。

·         继承自EventArgs的类型应该以EventArgs结尾。

1、委托声明原型中的Object类型的参数代表了Subject,也就是监视对象,在本例中是 Heater(热水器)。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。

2、EventArgs 对象包含了Observer所感兴趣的数据,在本例中是temperature。

上面这些其实不仅仅是为了编码规范而已,这样也使得程序有更大的灵活性。比如说,如果我们不光想获得热水器的温度,还想在Observer端(警报器或者显示器)方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得很麻烦,而如果我们将热水器的引用传给警报器的方法,就可以在方法中直接访问热水器了。

现在我们改写之前的范例,让它符合 .Net Framework 的规范:

using System;

using System.Collections.Generic;

using System.Text;

 

namespace Delegate {

   // 热水器

  public class Heater {

    private int temperature;

    public string type = "RealFire 001";    // 添加型号作为演示

    public string area = "China Xian";     // 添加产地作为演示

    //声明委托

    public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);

    public event BoiledEventHandler Boiled; //声明事件

 

    // 自定义EventArgs 定义BoiledEventArgs类,传递给Observer所感兴趣的信息

    public class BoiledEventArgs : EventArgs {

      public readonly int temperature;

      public BoiledEventArgs(int temperature) {

        this.temperature = temperature;

      }

    }

 

    // 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视

    protected virtual void OnBoiled(BoiledEventArgs e) {

      if (Boiled != null) { // 如果有对象注册

       Boiled(this, e); // 调用所有注册对象的方法

      }

    }

    

    // 烧水。

    public void BoilWater() {

      for (int i = 0; i <= 100; i++) {

        temperature = i;

        if (temperature > 95) {

          //建立BoiledEventArgs 对象。

          BoiledEventArgs e = new BoiledEventArgs(temperature);

          OnBoiled(e); // 调用 OnBolied方法

       }

      }

    }

   }

 

   // 警报器

  public class Alarm {

    public void MakeAlert(Object sender, Heater.BoiledEventArgs e) {

      Heater heater = (Heater)sender;   //这里是不是很熟悉呢?

      //访问 sender 中的公共字段

      Console.WriteLine("Alarm{0} - {1}: ", heater.area, heater.type);

      Console.WriteLine("Alarm: 嘀嘀嘀,水已经 {0} 度了:", e.temperature);

      Console.WriteLine();

    }

   }

 

   // 显示器

  public class Display {

    public static void ShowMsg(Object sender, Heater.BoiledEventArgs e) {  //静态方法

      Heater heater = (Heater)sender;

      Console.WriteLine("Display{0} - {1}: ", heater.area, heater.type);

      Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", e.temperature);

      Console.WriteLine();

    }

   }

 

   class Program {

    static void Main() {

      Heater heater = new Heater();

      Alarm alarm = new Alarm();

 

      heater.Boiled += alarm.MakeAlert;  //注册方法

      heater.Boiled += (new Alarm()).MakeAlert;   //给匿名对象注册方法

      heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert);  //也可以这么注册

      heater.Boiled += Display.ShowMsg;    //注册静态方法

 

      heater.BoilWater();  //烧水,会自动调用注册过对象的方法

    }

   }

 }

 

输出为:

AlarmChina Xian - RealFire 001:

 Alarm: 嘀嘀嘀,水已经 96 度了:

AlarmChina Xian - RealFire 001:

 Alarm: 嘀嘀嘀,水已经 96 度了:

AlarmChina Xian - RealFire 001:

 Alarm: 嘀嘀嘀,水已经 96 度了:

DisplayChina Xian - RealFire 001:

 Display:水快烧开了,当前温度:96度。

// 省略 ...

 

六、泛型委托 

简单的泛型委托示例:

class Program 

    { 

        // 泛型委托,与普通委托类似,不同之处只在于使用泛型委托要指定泛型参数         

        public delegate T MyGenericDelegate<T>(T obj1,T obj2);  

        int AddInt(int x, int y) 

        { 

            return x + y; 

        }   

        string AddString(string s1, string s2) 

        { 

            return s1 + s2; 

        }          

        static void Main(string[] args) 

        { 

            Program p = new Program();              

            MyGenericDelegate<int> intDel; 

            intDel = p.AddInt; 

            Console.WriteLine("int代理的值是{0}", intDel(100, 200));  

            MyGenericDelegate<string> stringDel; 

            stringDel = p.AddString; 

            Console.WriteLine("string代理的值是{0}", stringDel("aaa", "bbb")); 

        } 

    } 

为了方便开发,.NET基类库针对在实际开发中最常用的情形提供了几个预定义好的委托,这些预定义委托用得很广,比如在编写lambda表达式和开发并行计算程序时经常要用到他们。.NET提供的泛型委托包括Action、Func和Predicate 

1、Action<T> 泛型委托

Action是无返回值的泛型委托,Action至少0个参数,至多16个参数,无返回值。

·         Action 表示无参,无返回值的委托 

·         Action<int,string> 表示有传入参数int,string无返回值的委托

·         Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托 

·         Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托 

泛型委托与直接显示声明自定义委托的示例比较:

显示声明自定义委托:

delegate void DisplayMessage(string message);

public class TestCustomDelegate

{

   public static void Main()

   {

      DisplayMessage messageTarget;

      messageTarget = ShowWindowsMessage;

      messageTarget("Hello, World!");  

   }     

   private static void ShowWindowsMessage(string message)

   {

      MessageBox.Show(message);     

   }

}

Action<T> 用法。比起自定义委托,明显可以看出代码简洁了。

public class TestAction1

{

   public static void Main()

   {

      Action<string> messageTarget;

      messageTarget = ShowWindowsMessage;

      messageTarget("Hello, World!");  

   }     

   private static void ShowWindowsMessage(string message)

   {

      MessageBox.Show(message);     

   }

}

2、Func<T, TResult> 委托

Func是有返回值的泛型委托,Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

·         Func<int> 表示无参,返回值为int的委托

·         Func<object,string,int> 表示传入参数为object, string 返回值为int的委托

·         Func<object,string,int> 表示传入参数为object, string 返回值为int的委托

·         Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托   

下面是一个简单的普通委托来传方法的示例。

private delegate string Say();

public static string SayHello()

{

    return "Hello";

}

 

static void Main(string[] args)

{

    Say say = SayHello;

    Console.WriteLine(say());

    Console.ReadKey();

}

为了更方便,我们再来试试.Net默认带的委托。

public static string SayHello()

{

    return "Hello";

}

static void Main(string[] args)

{

    Func<string> say = SayHello;

    Console.WriteLine(say());

    Console.ReadKey();

}

如果需要参数的,还可以这样传一份。

public static string SayHello(string str)

{

    return str + str;

}

static void Main(string[] args)

{

    Func<string, string> say = SayHello;

    string str = say("abc");  

    Console.WriteLine(str);     //输出abcabc

    Console.ReadKey();

}

 3、Predicate

predicate 是返回bool型的泛型委托, Predicate有且只有一个参数,返回值固定为bool

·         predicate<int> 表示传入参数为int 返回bool的委托  

先来一个普通示例:

using System;

using System.Drawing;

public class Example

{

   public static void Main()

   {

      // Create an array of Point structures.

      Point[] points = { new Point(100, 200),

                         new Point(150, 250), new Point(250, 375),

                         new Point(275, 395), new Point(295, 450) };

 

      // Find the first Point structure for which X times Y 

      // is greater than 100000.

      Point first = Array.Find(points, x => x.X * x.Y > 100000 );

 

      // Display the first structure found.

      Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);

   }

}

上边的示例只不过使用 lambda 表达式来表示Predicate<T>委托,使用predicate 改造上边的示例:

using System;

using System.Drawing;

public class Example

{

   public static void Main()

   {

      // Create an array of Point structures.

      Point[] points = { new Point(100, 200),

                         new Point(150, 250), new Point(250, 375),

                         new Point(275, 395), new Point(295, 450) };

 

      // Define the Predicate<T> delegate.

      Predicate<Point> predicate = FindPoints;     

      // Find the first Point structure for which X times Y 

      // is greater than 100000.

      Point first = Array.Find(points, predicate);

      // Display the first structure found.

      Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);

   }

   private static bool FindPoints(Point obj)

   {

      return obj.X * obj.Y > 100000;

   }

}

4、Func与Action都支持Lambda的形式调用

一般的需求下,我们就使用微软定义的委托就足够了,这样减少了我们对委托的重复定义,可能有部分初学者见到Func<>,Action<>这样的代码肯定会很懵比,这只是你对新东西陌生罢了,多结合实例敲几遍,自然就会用了,它们其实就是微软封装定义好了的委托,没有什么特别的。我们上面的代码也可以使用Lambda的形式:

class Program

{

    static void Main(string[] args)

    {

        Func<int,int,int> add = (a, b) => a + b;

        Calculate(add, 10, 25);

        Console.ReadKey();

    }

    static void Calculate<T, Y, U>(Func<T, Y, U> ex, T a, Y b)

    {

        Console.WriteLine(ex(a, b) + "\n");

    }

}

这样写用Func就省去了定义委托这一步。

同样,其实在我们的webform,winform框架中,微软也给我们规范了一个委托的定义:

1

delegate void EvenHandler(object sender,   EventArgs e);

七、事件的详解

什么是事件?事件涉及两类角色:事件的发布者和事件的订阅者。触发事件的对象称为事件发布者,捕获时间并对其作出响应的对象叫做事件订阅者。 个人理解事件和委托的关系,相当于属性和字段的关系。

事件和委托的关系:在事件触发以后,事件发布者需要发布消息,通知事件订阅者进行事件处理,但事件发布者并不知道要通知哪些事件订阅者,这就需要在发布者和订阅者之间存在一个中介,这个中介就是委托。我们知道,委托都有一个调用列表,那么,只需要事件发布者有这样一个委托,各个事件订阅者将自己的事件处理程序都加入到该委托的调用列表中,那么事件触发时,发布者只需要调用委托即可触发订阅者的事件处理程序。 

事件的声明:事件就是类成员的一种,只是事件定义中包含一种特殊的关键字:event。事件的声明有两种方式: 

1、采用自定义委托类型。

2、采用EventHandler预定义委托类型,如下面代码:

1

2

//关键字  委托类型   时间名

public event  EventHandler   PrintComplete;

这两种方式基本相同,只不过第二种是.Net Framework中普遍采用的一种形式,因此建议尽量采用第二种方式。我们先来看看EventHandler委托的签名:

1

public delegate void EventHandler(Object   sender,EventArgs e);

从上面的签名可以看出:

1、EventHandler委托的返回类型为void;

2、第一个参数--sender参数,它负责保存触发事件的对象的引用,因为参数的类型是Object类型,因此它可以保存任何类型的实例;

3、第二个参数--e参数,它负责保存事件数据,这里是在BCL中定义的默认的EventArgs类,它位于System命名空间中,他不能保存任何数据。 

订阅事件:事件订阅者角色需要订阅事件发布者发布的事件,这样才能在事件发布时接受到消息并作出响应,事件事实上是委托类型,因此事件处理方法必须和委托签名相匹配。如果事件使用预定义的委托类型:EventHandler,那么匹配它的事件处理方法如下:

public void SomeEventHandler(object sender, EventArgs e)

{

    //..

}

有了事件处理方法,就可以订阅事件了,只需要使用加法赋值运算符(+=)即可。 

触发事件代码如下:

//检查事件是否为空

if (PrintComplete != null)

{

    //像调用方法一样触发事件,参数

    PrintComplete(this,new EventArgs();

}

 完整的一个事件例子:

namespace ConsoleApplication1

{

    public class Program

    {

        static void Main(string[] args)

        {

             Console.WriteLine("该做的东西做完,然后触发事件!");

             EventSample es = new EventSample();

             es.ShowComplete += es.MyEventHandler;

            es.OnShowComplete();

            Console.ReadKey();

        }

    }

    public class EventSample

    {

     //定义一个事件

        public event EventHandler ShowComplete;

    

     //触发事件

        public void OnShowComplete()

        {

            //判断是否绑定了事件处理方法,null表示没有事件处理方法

            if (ShowComplete != null)

            {

          //像调用方法一样触发事件

                ShowComplete(this, new EventArgs());

            }

        }

 

        //事件处理方法

        public void MyEventHandler(object sender, EventArgs e)

        {

            Console.WriteLine("谁触发了我?" + sender.ToString());

        }

    }

}

八、事件引起的内存泄露

1、不手动注销事件也不发生内存泄露的情况

我们经常会写EventHandler += AFunction; 如果没有手动注销这个Event handler类似:EventHandler –= AFunction 有可能会发生内存泄露。

public class Program

{

    static void ShowMemory()

    {

        Console.WriteLine("共用内存:{0}M", GC.GetTotalMemory(true) / 1024 / 1024);

    }

    static void Main(string[] args)

    {

        ShowMemory();

        for (int i = 0; i < 5; i++)

        {

            EventSample es = new EventSample();

            es.ShowComplete += es.MyEventHandler;

            GC.Collect();

            GC.WaitForPendingFinalizers();

            GC.Collect();

            ShowMemory();

        }

        Console.ReadKey();

    }

}

 

public class EventSample

{

    byte[] m_ExtraMemory = new byte[1024 * 1024 * 12];

    //定义一个事件

    public event EventHandler ShowComplete;

    //触发事件

    public void OnShowComplete()

    {

        //判断是否绑定了事件处理方法,null表示没有事件处理方法

        if (ShowComplete != null)

        {

            //像调用方法一样触发事件

            ShowComplete(this, new EventArgs());

        }

    }

    //事件处理方法

    public void MyEventHandler(object sender, EventArgs e)

    {

        Console.WriteLine("谁触发了我?" + sender.ToString());

    }

}

 上述代码输出如下:  

 

 从输出来看,内存被GC正常地回收,没有问题。

2、内存泄露的情况

我们来将代码改动一下

public class Program

{

    static void ShowMemory()

    {

        Console.WriteLine("共用内存:{0}M", GC.GetTotalMemory(true) / 1024 / 1024);

    }

    static void Main(string[] args)

    {

        ShowMemory();

       for (int i = 0; i < 5; i++)

       {

           Microsoft.Win32.SystemEvents.DisplaySettingsChanged += new EventHandler(new MyMethod().SystemEvents_DisplaySettingsChanged);

           GC.Collect();

           GC.WaitForPendingFinalizers();

           GC.Collect();

           ShowMemory();

       }

       Console.ReadKey();

   }

}

public class MyMethod

{

    byte[] m_ExtraMemory = new byte[1024 * 1024 * 12];

    public void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e){ }

}

输出结果如下:  

 

 从输出结果来看,内存已不能被GC正常回收。为什么会出现这种情况呢?我们来看看Microsoft.Win32.SystemEvents.DisplaySettingsChanged的源代码(省略前后部分):

public sealed class SystemEvents

{

    ... ...

    public static event EventHandler DisplaySettingsChanged

    ... ...

为什么会有差别,根本区别在于后者有个SystemEvents.DisplaySettingsChanged事件,而这个事件是静态的。

3、释放资源

如果我们希望释放资源,则我们需要在某个地方实现-=AFunction操作

public class Program

{

    static void ShowMemory()

    {

        Console.WriteLine("共用内存:{0}M", GC.GetTotalMemory(true) / 1024 / 1024);

    }

    static void Main(string[] args)

    {

        ShowMemory();

        for (int i = 0; i < 5; i++)

        {

            using (MyMethod myMethod = new MyMethod())

            {

                Microsoft.Win32.SystemEvents.DisplaySettingsChanged += new EventHandler(myMethod.SystemEvents_DisplaySettingsChanged);

            }

            GC.Collect();

            GC.WaitForPendingFinalizers();

            GC.Collect();

            ShowMemory();

        }

        Console.ReadKey();

   }

}

 

public class MyMethod : IDisposable

{

    byte[] m_ExtraMemory = new byte[1024 * 1024 * 12];

    public void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) { }

    public void Dispose()

    {

        Microsoft.Win32.SystemEvents.DisplaySettingsChanged -= new EventHandler(SystemEvents_DisplaySettingsChanged);

    }

}

输出如下:

  

增加了一个Dispose来实现 "-="功能就OK了。

4、注意静态、单例

静态对象生命周期很长,永远不会被GC回收,一旦被他给引用上了,那就不可能释放了。上面的例子就是被静态的DisplaySettingsChanged 引用导致不能被回收。  另外一个要注意的是Singleton单例模式实现的类,他们也是static的生命周期很长,要注意引用链,你的类是否被它引用上,如果在它的引用链上,就内存泄露了。

九、委托的三种调用 

本文将主要通过同步调用、异步调用、异步回调三个示例来讲解在用委托执行同一个加法类的时候的的区别和利弊

首先,通过代码定义一个委托和下面三个示例将要调用的方法:

public delegate int AddHandler(int a,int b);

public class 加法类

{

   public static int Add(int a, int b)

   {

       Console.WriteLine("开始计算:" + a + "+" + b);

       Thread.Sleep(3000); //模拟该方法运行三秒

       Console.WriteLine("计算完成!");

       return a + b;

   }
}

1、同步调用

委托的Invoke方法用来进行同步调用。同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行。代码如下

public class 同步调用

{

        static void Main()

        {

            Console.WriteLine("===== 同步调用 SyncInvokeTest =====");

            AddHandler handler = new AddHandler(加法类.Add);

            int result = handler?.Invoke(1, 2);

            Console.WriteLine("继续做别的事情。。。");

            Console.WriteLine(result);

            Console.ReadKey();

        }     

}

同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕的用户体验,这时候异步调用就很有必要了。

2、异步调用

异步调用不阻塞线程,而是把调用塞到线程池中,程序主线程或UI线程可以继续执行。委托的异步调用通过BeginInvoke和EndInvoke来实现。代码如下:

public class 异步调用

{

        static void Main()

        {

            Console.WriteLine("===== 异步调用 AsyncInvokeTest =====");

            AddHandler handler = new AddHandler(加法类.Add);

            //IAsyncResult: 异步操作接口(interface)

            //BeginInvoke: 委托(delegate)的一个异步方法的开始

            IAsyncResult result = handler.BeginInvoke(1, 2, null, null);

            Console.WriteLine("继续做别的事情。。。");

            //异步操作返回

            Console.WriteLine(handler.EndInvoke(result));

            Console.ReadKey();

        }

}

可以看到,主线程并没有等待,而是直接向下运行了。但是问题依然存在,当主线程运行到EndInvoke时,如果这时调用没有结束(这种情况很可能出现),这时为了等待调用结果,线程依旧会被阻塞。

异步委托,也可以参考如下写法:

Action<object> action=(obj)=>method(obj);

action.BeginInvoke(obj,ar=>action.EndInvoke(ar),null);

简简单单两句话就可以完成一部操作。

3、异步回调

用回调函数,当调用结束时会自动调用回调函数,解决了为等待调用结果,而让线程依旧被阻塞的局面。代码如下:

public class 异步回调

{

        static void Main()

        {

            Console.WriteLine("===== 异步回调 AsyncInvokeTest =====");

            AddHandler handler = new AddHandler(加法类.Add);

            //异步操作接口(注意BeginInvoke方法的不同!)

            IAsyncResult result = handler.BeginInvoke(1,2,new AsyncCallback(回调函数),"AsycState:OK");

            Console.WriteLine("继续做别的事情。。。");

            Console.ReadKey();

        }

 

        static void 回调函数(IAsyncResult result)

        {    

             //result 加法类.Add()方法的返回值

            //AsyncResult IAsyncResult接口的一个实现类,空间:System.Runtime.Remoting.Messaging

            //AsyncDelegate 属性可以强制转换为用户定义的委托的实际类。

            AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;

            Console.WriteLine(handler.EndInvoke(result));

            Console.WriteLine(result.AsyncState);

        }

}

我定义的委托的类型为AddHandler,则为了访问 AddHandler.EndInvoke,必须将异步委托强制转换为 AddHandler。可以在异步回调函数(类型为 AsyncCallback)中调用 MAddHandler.EndInvoke,以获取最初提交的 AddHandler.BeginInvoke 的结果。

4、需要注意的地方

(1)int result = handler.Invoke(1,2);

  为什么Invoke的参数和返回值和AddHandler委托是一样的呢?

  答:Invoke方法的参数很简单,一个委托,一个参数表(可选),而Invoke方法的主要功能就是帮助你在UI线程上调用委托所指定的方法。Invoke方法首先检查发出调用的线程(即当前线程)是不是UI线程,如果是,直接执行委托指向的方法,如果不是,它将切换到UI线程,然后执行委托指向的方法。不管当前线程是不是UI线程,Invoke都阻塞直到委托指向的方法执行完毕,然后切换回发出调用的线程(如果需要的话),返回。

所以Invoke方法的参数和返回值和调用他的委托应该是一致的。

(2)IAsyncResult result = handler.BeginInvoke(1,2,null,null);

  BeginInvoke : 开始一个异步的请求,调用线程池中一个线程来执行,

  返回IAsyncResult 对象(异步的核心). IAsyncResult 简单的说,他存储异步操作的状态信息的一个接口,也可以用他来结束当前异步。

  注意: BeginInvoke和EndInvoke必须成对调用.即使不需要返回值,但EndInvoke还是必须调用,否则可能会造成内存泄漏。

(3)IAsyncResult.AsyncState 属性:

  获取用户定义的对象,它限定或包含关于异步操作的信息。

 十、异步调用与多线程的区别 

随着拥有多个硬线程CPU(超线程、双核)的普及,多线程和异步操作等并发程序设计方法也受到了更多的关注和讨论。本文主要是想探讨一下如何使用并发来最大化程序的性能。

多线程和异步操作的异同 

多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别。多线程是实现异步的一个重要手段,但不是唯一手段,对以一个单线程程序也可以是异步执行的。 

异步操作的本质

所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。异步编程的目的就是为了能够是实现并行,但不仅是提高多处理器间的并行度,同时也是提高处理器与I/O处理器的并行度。非阻塞模式一般特指异步的I/O 操作,可以算是异步编程的一种类型。

线程的本质 

线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

异步操作的优缺点 

因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些初入,而且难以调试。

多线程的优缺点 

多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

适用范围 

在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往 往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处 理大量的并发操作时就不合适了。

对于CPU来说以下意味着什么

线程:意味了CPU的一组寄存器

进程:意味着CPU的页目录寄存器

IO:意味着一些端口或内存地址空间中一些地址

 


软考精简笔记

整合万金油

1、看到有技术人员出身做项目经理就要回答在信息系统工程中,开发和管理是两条不同的主线,开发人员所需要的技能与管理人员所需要的技能很不一样。角包定位可能不好没有站在项目经理的角度管理项目,所以需要给他培训。

2、看到身兼数职就要回答可能没有多少时间去学习管理知识,去从事管理工作。一人承担两个角包的工作,导致工作负荷过载,身心疲惫,其后果可能给全局带来不利影响。

3、看到新技术,就要想到风险,接着就是应该对大家进行培训、学习,然后监控技术风险,或者找合适的人选从事这项工作,最后实在不行就外包。

4、看到有人对项目不高意就要回答可能没有建立有效的沟通机制和方式、方法,缺乏有效的项目绩效管理机制,需要加强沟通。

5、看到变更的方面就一定是变更的三个要素:书面申请、审批和确认、跟踪变更过程。这三个方面缺一不可。

6、看到由客户验收不通过,往往需要说明验收标准没有得到认可或确认,没有验收测试规范 和方法等。

7、只要是与人有关的问题均可以找到沟通方面的答案。 也就是沟通不到位。

8、看到过了一段时间才发现为题就说监控不力,不能及时发现问题

9、看到里程碑或一些时间做的很紧促,就说没有冗余考虑风险的想法

10、看到因为外部因素导致的项目的延工等等就要想到没有考虑外在因素的影响这个可以结合变更5个理由来考虑。

11、看到有争执就要想到是不是沟通有问题,或者计划做的不够周明

12、看到多头汇报的问题,就要想到项目章程或者考虑多头回到导致信息沟通不畅通或者冲突

如何启动项目:

①识别需求②解决方案的确定③项目可行性分析④项目立项:⑤项目章程的确定。

可行性研究的内容:

①技术可行性分析②经济可行性分析:③运行环境可行性分析④其他方面的可行性分析(法律可行性社会可行性)。

可行性研究的步骤:

①明确项目规模和目标:②研究正在运行的系统:③建立新系统的逻辑模型:④导出和评价各种方案:⑤推荐可行性方案:⑥便携可行性研究报告:⑦递交可行性研究报告。

项目章程内容:

①项目需求,反应干系人的要求与期望:②项目必须实现的商业需求、项目概述或产品需求:③ 项目的目的或论证的结果:④任命项目经理并授权:⑤里程碑进度计划:⑥干系人的影响:⑦组织职能:③组织的、环境的和外部的假设:⑨组织的、环境的和外部的约束

制定计划通常存在的问题:

①项目管理计划不应由一人制定,应有顶目组参与;②项目计划缺少相关分计划,如质量计划、沟通计划等;③制定进度计划的方法不合理,没有预留一定的缓冲时时间;④项目计划缺少评审和审批环节;⑤没有处理好外部因素和内部因素带来的风险,缺乏有效的应对措施口;⑥项目发生变更时没有及时更新项目计划

编制项目计划:

 (l)明确目标(2)成立初步的项目团队(3)工作准备与信息收集(4)依据标准、模板,编写初步的概要的项目计划。(5)编写范围管理、质量管理、进度、预算等分计划(6)把上述分计划纳入项目计划然后对项目计划进行综合平衡、优化(7)项目经理负责组织编写项目计划。(8)评审与批准项目计划。

如何做好整体管理:

(1)建立企业级的项目管理体系和工作规范管理上不乱(2)明确可交付物(3)培训学习项目管理知识提高管理能力(4)做好经验的总结好各项计划(5)做好整体管理项目过程(6)加强变更管理与控制建立变更流程与体系(7)要有项目启动-可行性分析(8)要制定项目章程

整体实施过程中出现问题:

(1)在项目实施过程中没有及时传递绩效报告给客户,因此客户对项目进展和质量状况不了解(2)没有让客户即使对阶段交付成果签字确认 (3)由于没有售后服务的承诺,客户担心没有后续的保证 (4)合作气氛不良,客户存在某种程度的抵触情绪,双方缺乏信任感,

采取措施:

(1)就项目验收标准和客户达成共识,确定哪些主要工作完成就可以验收通过(2)就验收的步骤方法和客户达成共识。(3)就项目己经完成的程度让客户确认,例如出具系统使用报告让客户签字确认(4)向客户提出明确的服务承诺。使客户没有后顾之忧。

吸取的经验和教训:

(1)项目合同中要规定项目成果的证实验收标准验收步骤验收流程和运营维护承诺等内容(2)加强项目执行过程中的控制:加强变更控制、加强项目沟通管理加强计划执行的控制(3)项目经理还应注重和客户交往的技巧努力促成双方的良好合作氛围

范围说明书内容:

①项目目标:②产品范围描述:③项目的可交付物:④项目边界:⑤产品验收标准:⑥项目约束条件:⑦项目的假定。

范围管理可能问题:

①没有挖掘到全部隐性需求,缺乏精确的范围定义②没有有效的范围管理造成二次变更③对范围控制不足④没有和客户进行需求确认⑤没有对风险进行有效管理⑥没有对质量进行有效控

范围管理应对措施:

①对项目范围进行清晰定义,并根据定义对工作进行分解制定 WBS:②对项目进行合理估算对工作量有量化的把握:③对项目范围进行有效控制④重新定义项目范围必须得到高层和客户的确认⑤进行沟通管理协调多个项目干系人之间的矛盾

 

范围万金油:

(1)在开发合同中没有明确系统的需求,没有进行范围确认(2)对需求变更没有规范管理,变更没有依据。

WBS的主要作用:

(1)防止应该做的工作被遗漏掉,也防止镀金(2)方便与项目团队的沟通,项目成员很容易找到自己负责部分在整个项目中的位置 (3)防止不必要的变更(4)提供一个基本的资源估算依据 (5)帮助获取团队认同和创建团队

分解工作结构原则:

(1)在各层次上保持项目的完整性,避免遗漏必要的组成部分(2)一个工作单元只能从属于某个上层单元,避免变叉从属(3)相同层次的工作单元应有相同性质(4)工作单元应能分开不同的责任者和不同工作内容(5)便于项目管理进行计划和控制的管理需要6)最低层工作应该具有可比性,是可管理的,可定量检查的(7)应包括项目管理工作,包括分包出去的工作。(8)WBS的最低层次的工作单元是工作包。

项目范围管理存在的问题

(1)没有制定范围管理计划或者项目管理计划 (2)项目范围说明书内容不全面 (3)没有及时评估客户提出的变更要求对项目带来的影响并与客户及时沟通(4)变更不应由项目经理审批,应有 CCB 审批 (5)项目变更实施前没有及时变更合同(6)变更结果没有得到客户的确认

变更中常见的问题:

1.没有按照变更要求处理更过程2.变更要求没有留下书面记录3.是 否接受或拒绝变更不应由项目经理独自决定4.项目变更后有没有相应的变更合同 

范围管理整体变更基础知识点:

(1)范围变化会导致进度、成本、质量、合同等变化 (2)管理项目范围必须要制定范围管理计划,定义范围,范围确认和范围控制等活动3)需求、设计和项目管理计划要经过评审才能实施 (4)范围变更要遵循变更控制流程:变更申请、变更评估、变更审批、变更实施、变更确认、变更发布

保证项目进度措施:

①进度计划的贯彻:②调度工作:③抓关键活动的进度:④保证资源的及时供应:⑤加强组织管理工作:⑥加强进度控制工作。

加快进度、压缩工期方法:

①赶工:②快速跟进:③增加优质资源:④提高资源利用率:⑤外包和缩小项目范围。

监督和跟踪项目进度步骤:

①细化WBS,基于WBS和工时估算制订活动网络图,制订项目工作计划:②建立对项目工作的 监督和测量机制:③确定项目里程碑,并建立有效的评审机制:④对项目中发现的问题,及时采 取纠正和预防措施,并进行有效的变更管理。⑤使用有效的项目管理工具,提升项目管理的工作

 

进度万金油:

(1)项目经理经验不足,进度估算不准确(2)项目资源配置不足或者配置不合理(或人力)

经常出现的问题:

(1)团队成员没有及早参与,需求分析耗时长,要早期参与拉项目 (2)经验不足,进度计划制定不准,采取有效的历时估算方法和网络计划技术,制定进度计划 (3)考虑项目期间特定时期会对进度产生影响 (5)项目经理经验不足,进度估算不准确(6)资源与配置不足 (7)没有充分利用分配项目资源 (8)在安排进度时未考虑法定节假日的因素 (9)仅仅依靠某项目来估算项目的历时根据不充分(10)没有对项目的技术方案、管理计划进行详细的评审、需求没有经过确认 (11)增加人人员经验不足、沟通存在问题、加班使得人员的工作效率降低

解决方案:

(1)向公司申请增加资源,或使用经验丰富的员工(2)优化网络图,重排活动之间的颐序,压缩关键路径长度:(3)临时加班(赶工),尽可能补救耽误的时间或提升资源的利用效率: (4)将部分阶段的工作改为并行、内部流程优化: (5)变更原来的进度计划。根据前阶段的绩效,对后续工作重新估计,修订计划,并得到项目干系人同意: (6)加强同项目干系人的沟通:(7)加强对交付物、项目阶段工作的及时检查和控制,避免后期出现返工: (8)尽可能调配非关键路径上的资源用于关键路径上的任务: (9)优化外包、采购等环节并全程监控。

进度控制

(1)确定项目进度的当前状态。 (2)对引起进度变更的因素施加影响,以保证这种变化朝着有利的方向发展。 (3)确定项目进度己经变更。 (4)当变更发生时管理实际的变更。进度控制是整体变更控制过程的一个组成部分。

项目成本管理成本失控的原因

(1)对工程项目认识不足①对信息系统工程成本控制的特点认识不足,对难度估计不足②工程项目的规模不合理,一个大而全的项目往往导致工期很长,而且导致工程实施的技术 难度太高,导致技术人员的投入方面跟不上工程建设的需要③程项目的设计人员和实施人员缺乏成本意识,导致项目的设计不满足成本控制的要求④对项目成本的使用缺乏责任感,随意开支,铺张浪费

(2)组织制度不健全

①制度不完善②责任不落实乏成本控制的责任感在项目各个阶段和工作包没有落实具体的成本控制人员③承建单位项目经理中没有明确的投资分工导致对投资控制的领导督查不力

(3)方法问题

①缺乏用于项目投资控制所需要的有关报表及数据处理的方法。②缺乏系统的成本控制程序和明确的具体要求,在项目进展不同阶段对成本控制任务的要求 不明确,在项目进展的整个过程中缺乏涟贯性的控制。③乏科学、严格、明确且完整的成本控制方法和工作制度④缺乏对计算机辅助投资控制程序的利用⑤缺乏对计划值与实际值进行动态的比较分析,并及时提供各种需要的状态报告及经验总结

(4)技术的制约

①由于进行项目成本估算发生在工程项目建设的早期阶段,对项目相关信息了解不深项目规划设计不够完善不能满足成估算的需求① 用的项目成本估算方法不恰当,与项目的实际情况不符③目成本计算的数据不准确或有漏项,从而导致计算成本偏低④计者未对设计方案进行优化,导致项目设计方案突破项目成本目标⑤资或设备价格的上涨,大大超过预期的浮动范围⑥项目规划和设计方面的变更引起相关成本的增加⑦对工程实施中可能遇见的风险估计不足,导致实施成本大量增加

进度落后的措施

用高效人员替代低效人员(2)加班或者赶工在在防范风险的情况下并行施工

进度超前的措施

(1)抽调部分人员放慢工作进度 (2)采取措施控制成本(3)对不同的任务采取不同的成本和进度措施必要时候调整成本基准

 

成本控制:

 (1)对造成成本基准变更的因素施加影响 (2)确保变更请求获得同意 (3)当变更发生时,管理这些实际的变更 (4)保证潜在的成本超支不超过授权的项目阶段资金和总体资金 (5)监督成本执行,找出与成本基准的偏差 (6)准确记录所有的与成本基准的偏差(7)防止错误的,不恰当的或未获批准的变更纳入成本或资源使用报告中(8)就审定的变更,通知项目干系人(9)采取措施,将预期的成本超支控制在可接受的范围内

项目成本估算:1)类比估算 2)确定资源费率 3)自下而上估算 4)参数估算5)项目管理软件 6)供应商投标分析7)准备金分析

项目成本预算:1)成本汇总2)准备金分析3)参数估算4)资金限制平衡

项目成本控制:1)成本变更控制系统2)绩效衡量分析 3)预测技术4)项目绩效审核5)项目管理软件6)偏差管理

项目成本估算主要步骤:

(1)识别并分析成本的构成科目。 (2)根据己识别的项目成本构成科目,估算每一科目的成本大小。 (3)分析成本估算结果,找出各种可以相互替代的成本,协调各种成本之间的比例关系。

成本预算的步骤

 (1)将项目总成本分摊到项目工作分解结构的各个工作包。分解按照自顶向下,根据占用资 源数量多少而设置不同的分解权重。 (2)将各个工作包成本再分配到该工作包所包含的各项活动上。 (3)确定各项成本预算支出的时间计划及项目成本预算计划。

 

项目质量管理

 (1)确立质量标准体系 (2)对项目实施进行质量监控 (3)将实际与标准对照(4 纠偏纠错

质量保证的基本内容:

 (1)制定质量标准。(2)制定质量控制流程(3)提出质量保证所采用方法和技术。 (4)建立质量保证体系。

质量控制基本步骤:

(1)选择控制对象2)为控制对象确定标准或目标3)制定实施计划,确定保证措施(4)按计划执行(5)对项目实施情况进行跟踪监测、检查,并将监测的结果与计划或标准相比较。 (6)发现并分析偏差。 (7)根据偏差采取相应对策:

质量管理可能遇到的问题:

(1)质量保证人员经验不足(2)没有制定和实施合理的、可操作性的质量管理计划(3)项目经理在项目质量管理方面的经验欠缺:(4)进度计划制定的不合理(5)测试过程的阶段安排不合理,软件系统的测试时间不足(6)需求分析、系统设计阶段的质量控制可能不到位、缺少评审环节(7)测试过程中配置管理工作未到位(8)项目缺乏质量标准和质量规范(9)没有建立项目的质量保证体系:

解决措施:

 (1)应使用有相关行业经验、项目经验和质量管理经验的质量保证人员: (2)应该科学制定和实施质量管理计划: (3)重视软件项目的测试环节,安排必要的时间,采用合理的方法进行充分测试: (4)应加强需求和设计方案的评审和质量控制工作: (5)应重视软件开发过程中的质量保证工作,采用相应的工具和技术,避免将检查、测试作为项目质量保证的唯一方法: (6)应加强项目实施过程中的配置管理工作:(7)应建立项目的质量管理体系,包括制定可行的过程规范和质量目标、质量标准: (8)对发现的缺陷进行统计分析,确保软件质量:

 

人力资源计划内容:

(1)角色和职责的分配(2)项目的组织结构图(3)人员配备管理计划。

成功的项目团队的特点:

1)团队目标明确:2)团队组织结构清晰岗位明确:3)有成文或习惯的工作流程和方法,且流程简明有效:4)项目经理对团队成员有明确的考核和评价标准:5)共同制定并遵守的组织纪律:

沟通计划编制步骤:

(l)确定干系人的沟通信息需求,即哪些人需要沟通,谁需要什么信息,什么时候需要以及 如何把信息发送出去。(2)描述信息收集和文件归档的结拘。 (3)发送信息和重要信息的格式,主要指创建信息发送的档案:获得信息的访问方法。 通常沟通计划编制的第一步就是千系人分析,得出项目中沟通的需求和方式

沟通管理计划内容:

(1)项目干系人沟通要求。(2)对要发布信息的描述,包括格式、内容和详尽程度(3)信息接收的个人或组织(4)传达信息所需的技术或方法,如备忘录、电子邮件和/或新闻发布等(5)沟通频率,如每周沟通等(6)上报过程,对下层无法解决的问题,确定问题上报的时间要求和管理链。 

项目干系人分析:

进行项目干系人识别:②分析项目干系人的重要程度:③进行项目干系人的支持度分析:④ 针对不同项目干系人,特别是重要的项目干系人,给出管理项目干系人的建议,并予以实施。

①使用项目管理信息系统:②建立沟通基础设施:③使用项目沟通模版:④把握项目沟通基本原 则:⑤发展更好的沟通技能:⑥把握人际沟通风格:⑦进行良好的冲突管理。

如何召开高效会议:

①事先制订一个例会制度:②放弃可开可不开的会议:③明确会议的目的和期望结果:④发布会议通知:⑤在会议之前将会议资料发给参会人员:⑥可以借助视频设备:⑦明确会议规则:③会议后要总结、提炼结论:⑨会议要有纪要:⑩做好会议的后勤保障

有效报告内容:

 (l)项目的进展和调整情况2)项目的完成情况(3)项目总投入、资金到位情况(4)项目资金实际支出情况(5)项目主要效益情况(6)财务制度执行情况(7)项目团队各职能团队的绩效(8)项目执行中存在的问题及改进措施。

人力资源可能问题:

①缺乏足够的项目管理能力和经验:②兼职过多,精力和时间不够用,顾此失彼:③没有进 入管理角色,定位错误,疏于对项目的管理:④新人缺乏培训和全程的跟踪和监控:⑤没有进行 良好的冲突管理。

应对措施:

①事先制定岗位的要求、职责和选人的标准,并选择合适的人选:②对工作进行全面估算, 如果有人负荷过重,需要找人代替,解决负载平衡问题:③事前沟通并对相应人员明确要求,明 确角色的轻重缓急,促使尽快转换角色:④上级应该注意平时对人员的培养和监控:⑤对项目团 队进行有效的冲突管理。

团队组建常见问题:

①招募不到合适的项目成员:②团队的组成人员尽管富有才干,但却很难合作:③团队气氛 不积极,造成项目团队成员的士气低落:④项目团队的任务和职责分配不清楚:⑤人员流动过于频繁。

产生原因:

①没有能够建立人力资源获取和培养的稳定机制:②没有完整识别项目所需的人力资源种类、 数量和相关任职条件:③没有建立一个能充分、有效发挥能力的团队:④没有清楚地分配工作职 责到个人或人力单元。

应对措施:

①建立稳定的人力资源获取和培养机制:②在项目早期,进行项目的整体人力资源规划,明 确岗位设置、工作职责和协作关系:③进行项目团队建设,加强团队沟通,建立合作氛围:④根 据项目团队成员的工作职责和目标,跟踪工作绩效,及时予以调整和改进,提升项目整体绩效。

保证团队沟通颐畅的六点措施:

沟通基本原则:

①沟通内外有别:②非正式的沟通有助于关系的融洽:③采用对方能接受的沟通风格:④沟 通的升级原则:⑤扫除沟通的障碍。

 

合同可能会出现的问题:

 (1)合同没订好,没有就具体完成的工作形成明确清晰的条款 (2)甲方没有对需求及其变更进行统一的组织和管理 (3)缺乏变更的接收/拒绝准则 (4)项目干系人及其关系分析不到位,范围定义不全面、不准确 (5)甲乙双方对项目范围没有达成一致认可或承诺 (6)缺乏项目全生命周期的范围控制(7)缺乏客户/用户参与

采取以下措施:

合同谈判阶段 (1)缺的明确的工作说明书或更细化的合同条款(2)在合同中明确双方的权利和义务,尤其是关于变更问题 (3)采取措施,确保合同签约双方对合同的条款理解是一致的

计划阶段

(1)编制项目范围说明书(2)创建工作的分解结构(3)制定项目的范围管理计划

执行阶段

(1)在项目执行过程中加强对易分解的各项任务的跟踪和记录 (2)建立与项目干系人进行沟通的统一渠道 (3)建立整体变更控制的规程并执行 (4)加强对项目阶段性成果的平审核确认

变更合同方法:

(1)首先确定合同变更量清单,然后确定变更价款。 (2)合同中己有适用于项目变更的价格,按合同己有的价格变更合同价款。 (3)合同中只有类似于项目变更的价格,可以参照类似价格变更合同价款。 (4)合同中没有适用或类似项目变更的价格,由承包人提出适当的变更价格,经监理工程师和业 主确认后执行。

合同履行

对于合同不明确的情况,应驾先协商,达成补充协议。达不成协议的,依照合同其他条款或 交易习惯确定。

(1)当事人对标的物的质量要求不明确的,按国家标准和行业标准。没有这些标准的,按产 品通常标准或符合合同目的的标准。

(2)履行地点不明确时,按标的性质不同而定:接受货币在接受方,交付不动产的在不动产 所在地,其他标的在履行义务方所在地。 (3)履行期限不明的,债务人可随时履行,债权人可随时要求履行,但应给对方必要的准备 时间。(4)履行费用负担不明确的,由履行义务一方负担。履行费用是履行义务过程中各种附随发 生的费用。

合同变更管理

(1)变更的提出。合同签约各方都可以向监理单位(或变更管理委员会)提出书面的合同变

请求。(2)变更请求的审查。合同签约各方提出的合同变更要求和建议,必须首先交由监理单位(或 变更管理委员会)审查后,提出合同变更请求的审查意见,并报业主。3)变更的批准。监理单位(或变更管理委员会)批准或拒绝变更。 (4)变更的实施。在组织业主与承包人就合同变更及其他有关问题协商达成一致意见后,由监理单位(或变更管理委员会)正式下达合同变更指令,承包人组织实施。

索赔的流程:

(1)提出索赔要求(2)报送索赔资料(3)监理工程师答复。(4)监理工程师逾期答复后果。(5)持续索赔(6)仲裁与诉讼。

合同的 4 种违约方式

 (1)继续履行。(2)采取补救措施(如质量不符合约定的,可以要求修理、更换、重作、退货、减少价款或 报酬等)。(3)赔偿损失(4)支付约定违约金或定金。

 

项目文档和配直管理问题:

(1)缺乏项目整体管理和权衡(2)缺乏变更控制规程(3)缺乏项目干系人沟通:(4)缺乏配 置管理:(5)缺乏整体版本管理:(6)缺乏各种单元测试和集成测试:

应对措施

(1)针对目前系统建立基线(2)梳理变更脉络,确定统一的最终需求和设计(3)梳理配置 项及其历史版本(4)对照最终需求和设计逐项分析现有配置项及历史版本的符合情况(5)根据 分析结果由干系人确定整体变更计划并实施(6)加强单元接口测试与系统的集成测

配直管理的流程:

 (1)建立并维护配置管理的组织方针(2)制定项目配置管理计划(3)确定配置标识规则 (4)实施变更控制(5)报告配置状态(6)进行配置审核(7)进行版本管理和发行管理

配直识别内容:

(1)识别需要受控的软件配置项(2)给每个产品和它的组件及相关的文档分配唯一的标识(3)定义每个配置项的重要特征以及识别其所有者(4)识别组件、数据及产品获取点和准则(5)建立和控制基线(6)维护文档和组件的修订与产品版本之间的关系

建立配直管理步骤

1)组建配置管理方案构造小组(2)对目标机构进行了解、 评估(3)配置管理工具及其提供商评估(4)制订实施计划(5)定义配置管理流程(6)试验项 目的实施(7)全面实施。

 

项目总结意义:

 (l)了解项目全过程的工作情况及相关的团队或成员的绩效状况。 (2)了解出现的问题并进行改进措施总结。 (3)了解项目全过程中出现的值得吸取的经验并进行总结。 (4)对总结后的文档进行讨论,通过后即存入公司的知识库,从而纳入企业的过程资产。

变更的常见原因: (l)产品范围(成果)定义的过失或者疏忽。 (2)项目范围(工作)定义的过失或者疏忽。 (3)增值变更。 (4)应对风险的紧急计划或回避计划。(5)项目执行过程与项目基准要求不_致带来的被动调整。(6)外部事件。

变更的流程:

1)提出与接受变更申请;2)对变更的初审;3)变更方案论证;4)项目管理委员会 (变更控制委员会)审查;5)发出变更通知并开始实施;6)变更实施的监控;7)变更效果的评估;8) 判断发生变更后的项目是否己经纳入正常轨道

 

变更管理的原则内容:

(1)基准管理 (2)建立变更控制流程 (3)完整体现变更的影响 (4)明确组织分工 (5)妥善保存变更产生的相关文档

有可能的问题:

①对用户的要求未进行记录:②对变更的请求未进行足够的分析,也没有获得批准③在修改的过程中没有注意进行版本管理:④修改完成后未进行验证:⑤修改的内容未和项目干系人进行沟通。

导致的后果:

乏对变更请求的记录可能会导致对产品的变更历史无法追溯,并会导致对工作产物的整 体变化情况失去把握:②缺乏对变更请求的分析可能会导致后期的变更工作失误:③在修改过程 中不注意版本管理,一方面可能会导致当变更失败时无法进行复原:另一方面,对于组织财富和 经验的积累也是不利的:④修改完成后不进行验证则难以确证变更是否正确实现:⑤未与项目干系人进行沟通可能会导致项目干系人的工作之间出现不一致之处:

答以下几点 (1)在项目功能和标准不明确的时候就签订了合同,为后来的项目变更埋下了隐患 (2)没有建立项目变更管理制度 (3)变更请求没有经过评估,没有评估产生的费用和技术要求,也没有签字确认(4)变更实施时没有考虑对系统其他功能的影响,也没有考虑能否实现。 (5)变更后没有进行验证 (6)没有对变更后的内容进行存档,也没有通知给相关的项目干系人。

实施变更之前有4个重要控制点:授权、审核、评估和确认 (1)授权:事先明确客户方有权提出变更申请的人员和实施方有权处理变更的人员,并要控制双方的人数 (2)审核:对变更进行必要的审核,决定是否需要修改和什么时候修改 (3)评估:对变更的影响进行评估,要让客户了解变更的后果。(4)确认:让客户确认是否接受变更的代价。

管理收尾包括

确认项目或者阶段己满足所有赞助者、客户,以及其他项目干系人需求的行动和活动。 (2)确认己满足项目阶段或者整个项目的完成标准,或者确认项目阶段或者整个项目的退出标准 的行动和活动。 (3)当需要时,把项目产品或者服务转移到下一个阶段,或者移交到生产和/或运作的行动和活 动。 (4)活动需要收集项目或者项目阶段记录、检查项目成功或者失败、收集教训、归档项目信息, 以方便组织未来的项目管理。

合同收尾

(1)识别和确认项目的阶段和主要可交付物。首先识别出项目生命期的各个阶段,然后把 每阶段的交付物明确和确认出来。(2)分解并确认每一组成部分是否分解得足够详细。一般来讲至少分解到可以合理的对其 进行成本和历时的估算为止。(3)确认项目主要交付成果的组成要素。交付成果的组成要素应当用有形的、可检验的结 果来描述,以便据此进行绩效评估。(4)核实分解的正确性。核对分解是否正确:

采购管理计划:

①采用的合同类型。②是否采用独立估算作为评估标准,由谁来准备独立估算?何时进行独立估算。③如果项目的执行组织设有采购、合同或者发包部门,项目管理团队本身能采取哪些行动?④标准的采购文件(如果需要的话)。⑤管理多个供应商。⑥协调采购与项目的其他方面,例如确定进度与绩效报告。⑦能对计划的采购造成影响的任何束和假定。

③处理从卖方购买产品所需的提前订货期,并与他们一起协调项目进度制订过程。

⑨进行"自制,外购"决策,并与活动资源估算过程、制订进度计划过程联系起来。

⑩确定每个合同中规定的可交付成果的日期安排,并与进度制订过程、进度控制过程相协调。

工作说明书的格式:

 (1)前言。对项目背景等信息作简单描述。(2)项目工作范围。详细描述项目的服务范围,包括业务领域、流程覆盖、系绕范围及其他等。 (3)项目工作方法。项目拟使用的主要方法。 (4)假定。项目进行的假定条件,具体内容需双方达成。 (5)工作期限和工作量估计。项目的时间跨度和服务期限,项目,需评估服务工作人天,并估算 项目预算。 (6)双方角色和责任。分为供应商的职责和发包商的职责,对于按人天计算费用的并对关键角色 的工作职责进行描述。 (7)交付件。列出项目的主要交付物的资料,并对交付件的内容与质量要求进行描述。 (8)完成以及验收标准。列出项目的完成标准和阶段完成标准,完成标准作为项目验收的依据内 容。 (9)服务人员。列出供应商的人员名单及顾问资格信息。描述在什么情况下可进行供应商人员的变更

 

通用:

1、事先要制订岗位的要求、职责和选人的标准。

2、缺乏对变更请求的记录可能会导致对产品的变更历史元法追溯,并会导致对工作产物的整体 变化情况失去把握。

3、缺乏对变更请求的分析可能会导致后期的变更工作失误。

4、在修改过程中不注意版本管理,一方面可能会导致当变更失败时元法进行复原:另一方面, 对于组织财富和经验的积累也是不利的。

5、修改完成后不进行验证则难以确证变更是否正确实现。

6、未与项目干系人进行沟通可能会导致项目干系人的工作之间出现不一致之处。

7、就项目验收标准和客户达成共识,确定哪些主要工作完成即可验收通过。

8、就项目验收步骤和方法和客户达成共识。

9、就项目已经完成的程度让用户确认。例如出具系统试用报告,请客户签字确认。

10、向客户提出明确的服务承诺,使客户没有后顾之忧。

11、加强项目执行过程中的控制,及时向客户提供项目绩效报告,让客户了解项目进展:设置对阶段性成果的验收,并让客户对阶段性交付成果进行签字确认:范围的变更要按照变更控制 程序操作。

12、项目文档要齐全,使项目进展有据可查。

13、项目经理应及时与客户进行沟通,努力促成双方的良好合作氛围。

14、加强沟通。争取客户能够对项目范围以及需求、设计、验收标准进行确认,避免后期频繁 出现变更。加强开发、测试、布线等人员的协调,保持工作的衔接,步调和内容一致,避免产 生失误。

15、加强对阶段工作的检查和控制,避免后期出现返工。

16、首先应对项目组成员进行沟通需求和沟通风格的分析。

17、对于具有不同沟通需求和沟通风格的人员组合设直不同的沟通方式。

19.关于全生命周期的范围管理,在合同谈判阶段:取得明确的工作说明书或更细化的合同条 款、在合同中明确双方的权利和义务,尤其是关于变更问题、采取措施,确保项目干系人对合 同的理解是一致的。计划阶段:编制项目范围说明书、创建项目的工作分解结构(WBS)、制定 项目的范围管理计划。执行阶段:在项目执行过程中加强对已分解的各项任务的跟踪和记录、建 立与项目干系人进行沟通的统一渠道、建立整体变更控制的规程并执行、加强对项目阶段性成 果的评审和确认:

20、建立健全项目管理制度并监管其执行

21、明确项目工作的交付物,建立和实施项目的质量评审机制。

22、建立项目的变更管理机制,识别变更中的利益相关方并加强沟通。

23、加强对项目团队成员和相关人员的项目管理培训

24、引入合适的项目管理工具平台,提升项目管理工作效率。

25、明确目标、责任和奖惩机制,提高员工的工作绩效。

26、确定项目的里程碑,并建立有效的评审机制

27、应该首先制定项目的质量管理计划,然后在项目的实施过程中,进行质量控制,每隔一定 时间如阶段末实施质量计划中确定的、系统的质量活动例如审计或同行审查,以评价项目的整 体绩效,确保项目为了高足项目干系人的期望实施了所有必须过程。

28、应注意资源和知识的积累,保障资源的可用性,如通过培训、设直 A 角 B 角等办法,解决 关键技术人员的后备问题,以应对关键人员流失的风险

29、及早发现问题的苗头,并及时与公司管理层沟通和协商

30、在项目的进行过程中,将风险管理纳入日常工作,建立风险预警机制31、加强文档管理,妥善保存变更产生的相关文档、确保其完整、及时、准确、清晰、适当的 时候可以引入配直管理工具 32、多与企业员工进行正式与非正式的沟通,适当激励项目团队, 以赢得大家的信任:

33、寻求公司领导层支持

34、对已完成工作和剩余工作进行评估,重新进行资源平衡,如果有问题,应及时进行协调

35、建立清晰的工作流程和沟通机制

36、鼓励团队成员之间建立参与和分享的氛围

37、应安排独立于项目组的质量保证人员负责质量保证工作

38、对软件开发的过程实施质量审计

39、注重对需求和设计等开发过程文件的技术评审工作。

40、注重测试工作,应安排相对独立的测试人员

41、对发现的缺陷进行统计分析,确保软件质量。

42、加强与外包公司的沟通、监控,随时了解项目进度,出现问题及时纠偏

43、向甲方报告进度拖延实情,取得甲方的谅解,就项目的后续开发计划达成一致,并承担相 应的责任

44、遵循整体变更控制流程,记录相关客户需求,对需求变更可能带来的影响进行较全面的评 估,形成经建设方签字确认的新需求文件,并提交 CCB 审批:将相关的变更信息及时有效的通 知相关的项目干系人

45、强化对项目的配直管理,以及对整个项目实施过程的监督与控制

46、应建立项目的质量管理体系,包括制定可行的过程规范和质量目标、质量标准

47、提出合理有效的质量整改措施(如建议的纠正措施、对项目计划可能的更新等)

48、请求公司的管理层出面去与甲方协调

49、要在合同评审阶段参与评审,在合同中明确相应的项目目标和进度

50、阶段验收前,文档要齐全,阶段目标要保证实现,后期目标调整要有承诺

51、就完成的工作与建设方沟通确认,并请建设方签字:就待完成的工作列出清单,以便完成 时请建设方确认:必要时可签署一份售后服务承诺书,将此项目周期内元法完成的任务做一个 备忘,承诺在后续的服务期内完成,先保证项目能按时验收

52、严格执行公司的质量管理体系规范工作流程,制定质量管理计划:执行质量保证计划:资源(如:人、财、物等)加强后续质量保证工作:加强后期的质量控制和测试:提 前加强产品交互后的客户服务和维护工作:加强沟通:建议必要时修改质量基准争取以最小的 代价获得用户认可。

53、项目管理计划不应由一人制定,应有项目组参与,另外,需要注意其评审和审批环节

54、聘请经验丰富的人员

55、制定全面有效的配直管理计划,包括建立配直管理环境、组织机构、成本、进度等,在配 直管理计划中详细描述,建立示例配直库、配直标识管理、配直库控制、配直的检查和评审、 配直库的备份、配直管理计划附属文