Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Asynchronous Setup Grid

4.33/5 (2 votes)
5 Oct 2007CPOL2 min read 1   379  
A custom asynchronous setup with progress indicator.

Screenshot - SetupGrid.jpg

Introduction

If there is a need for a setup component that can read an XML setting file (SetupScripts.xml) and run methods or scripts defined in it asynchronously, then this Setup Grid component is what you are looking for. To use this component, the methods in an assembly, a batch file, or a path to a T-SQL file can be defined in SetupScripts.xml and we can call StartSetup() to execute them asynchronously. That means, when the setup is in progress, other operations are not suspended.

Solution

SetupGridUC is a UserControl that contains a DataGridView to show the scripts and the progress status when the setup is running. A typical scenario of using the SetupGridUC component is as follows:

  1. Initialize SetupGridUC from the SetupScripts.xml file using the Load() method.
  2. Start setup using the StartSetup() method of SetupGridUC and also StopSetup(false) when it is started.
  3. In order to do some actions (e.g., disable buttons) when the setup is being started or finished, use the following events:
    • void stpGrid_ProgressFinished(object sender, EventArgs e) is called when the setup finishes.
    • void stpGrid_ProgressStarted(object sender, EventArgs e) is called when the setup starts.

Implementation

The StartSetup() method starts the setup process asynchronously by calling the ExecuteScript() method of the SetupGridUC component using BeginInvoke().

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

Using visual components, like refreshing the DataGridView from another thread of execution, can cause a Cross-thread operation not valid exception. To bypass this exception, the Invoke() method of the component should be used. SafeInvoke() uses the Invoke() method of a component to call a parameter-less method (the void MethodName() delegate) in the component:

C#
private delegate void VoidDelegate();
...

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

To refresh asyncSetupGrid in another thread, use the SafeInvoke() method as follow:

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

Note: The void command_Progress event is called from another thread, so the visual components should use Invoke() to call a method.

The scripts or methods can be defined in SetupScripts.xml as follows:

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

Tag meanings:

XML
<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>

Deployment

This sample contains two assemblies:

  1. Main.exe as the executable to host the SetupGrid component.
  2. SetupGrid.dll as the library that contains the SetupGridUC component.

In order to test the SQL scripts, create a database in SQL Server and add proper connection settings to the database in Properties/Settings.settings file.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)