65.9K
CodeProject 正在变化。 阅读更多。
Home

异步设置网格

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2007年10月6日

CPOL

2分钟阅读

viewsIcon

31936

downloadIcon

399

带有进度指示器的自定义异步设置。

Screenshot - SetupGrid.jpg

引言

如果需要一个可以读取 XML 设置文件 (SetupScripts.xml) 并在其中异步运行定义的方法或脚本的设置组件,那么此 Setup Grid 组件正是您所寻找的。要使用此组件,可以在 SetupScripts.xml 中定义程序集中的方法、批处理文件或 T-SQL 文件的路径,并且我们可以调用 StartSetup() 来异步执行它们。这意味着,当设置正在进行时,不会暂停其他操作。

解决方案

SetupGridUC 是一个 UserControl,包含一个 DataGridView,用于在设置运行时显示脚本和进度状态。 使用 SetupGridUC 组件的典型场景如下所示

  1. 使用 Load() 方法从 SetupScripts.xml 文件初始化 SetupGridUC
  2. 使用 SetupGridUCStartSetup() 方法启动设置,并在启动时使用 StopSetup(false)
  3. 为了在设置开始或结束时执行某些操作(例如,禁用按钮),请使用以下事件
    • void stpGrid_ProgressFinished(object sender, EventArgs e) 在设置完成时调用。
    • void stpGrid_ProgressStarted(object sender, EventArgs e) 在设置开始时调用。

实现

StartSetup() 方法通过使用 BeginInvoke() 调用 SetupGridUC 组件的 ExecuteScript() 方法来异步启动设置过程。

private MethodDelegate methodDelegate;
...
asyncResult = methodDelegate.BeginInvoke(null, null);

使用视觉组件(例如,从另一个执行线程刷新 DataGridView)可能会导致 Cross-thread operation not valid 异常。为了绕过此异常,应使用组件的 Invoke() 方法。 SafeInvoke() 使用组件的 Invoke() 方法来调用组件中的一个无参数方法(void MethodName() 委托)

private delegate void VoidDelegate();
...

private void SafeInvoke(Control ctrl, VoidDelegate delgt)
{
    if (ctrl.InvokeRequired)
    {
        VoidDelegate d = new VoidDelegate(delgt);
        ctrl.Invoke(d, new object[] { });
    }
}

要在另一个线程中刷新 asyncSetupGrid,请使用 SafeInvoke() 方法,如下所示

private void command_Progress(object sender, ProgressEventArgs e)
{
    /// Call Refresh method of asyncSetupGrid using Invoke
    SafeInvoke(asyncSetupGrid, Refresh);
}

注意: void command_Progress 事件是从另一个线程调用的,因此视觉组件应使用 Invoke() 来调用方法。

脚本或方法可以在 SetupScripts.xml 中定义,如下所示

<tblSetupScripts>
    <ID>2</ID>
    <Name>S3</Name>
    <Title>Execute SQLQuery.sql against Database</Title>
    <Script>SQLQuery.sql</Script>
    <Kind>SQLScript</Kind>
</tblSetupScripts>

标签含义

<Name>:
    Name tag should be a unique name that user can assign to the script to be run
<Title>:
    Title tag is an explanation for the script
<Script>:
    Script tag meanings depend on <Kind> tag that can be set as follows:
<Kind>Method</Kind>
    <Script>
    {Assembly file name}, {Namespace. class name}, {Method name}
    /// <summary>
    /// This method is being called using reflection.
    /// It is defined in SetupScripts.xml file.
    /// Developer should pass following two delegate parameters
    /// to it that are doing some actions on calling SetupGrid object.
    /// </summary>
    /// <param name="doProgress"> This method sets progress bar
    ///           status in the subject row of the SetupGrid </param>
    /// <param name="doHalt"> This method returns true
    ///           if user stops the setup process </param>

    public void Mehtod(SetupGrid.ScriptCommands.ProgressDelegate doProgress, 
                       SetupGrid.ScriptCommands.HaltDelegate doHalt)
    {
        ...
    }
    </Script>

<Kind>SQLScript</Kind>
    <Script> {Path of SQL script to be executed}
    The T-SQL commands are separated using 'Go' 
    command from each other. For example:
    ...
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    ...
    </Script>
<Kind>BatchFile</Kind>
    <Script> { The path and file name of the Batch file to be executed}
    The batch file execution will open a Command Prompt 
    window and waits the command is finished.
    </Script>

部署

此示例包含两个程序集

  1. Main.exe 作为承载 SetupGrid 组件的可执行文件。
  2. SetupGrid.dll 作为包含 SetupGridUC 组件的库。

为了测试 SQL 脚本,请在 SQL Server 中创建一个数据库,并将适当的连接设置添加到 Properties/Settings.settings 文件中的数据库中。

© . All rights reserved.