Search code examples
c#delegatesdelegation

c# function which has method parameter value, or using delegate


I have two button click events in my window form application.

private void butProcess_1_Click(...)
{
    /// below parameters are just sample.
    Process_1(int_param1, decimal_param2, datetime_param3);
}

private void butProcess_2_Click(...)
{
    /// below parameters are just sample.
    Process_2(string_param1, guid_param2, byteArray_param3, bool_param4);
}

As those processes take longer time to finish executing, I need to display progress bar to user.
So I modify my event called butProcess_1_Click.

private void butProcess_1_Click(...)
{
    frmLoadingControl _frmLoadingControl = new frmLoadingControl();            
    _frmLoadingControl.Show(this);

    BackgroundWorker _BackgroundWorker = new BackgroundWorker();
    _BackgroundWorker.DoWork += (s, args) =>
    {
        this.Invoke(new MethodInvoker(() => this.Enabled = false));
        /// below parameters are just sample.
        Process_1(int_param1, decimal_param2, datetime_param3);
    };
    _BackgroundWorker.RunWorkerCompleted += (s, args) =>
    {
        _frmLoadingControl.Close();
        this.Invoke(new MethodInvoker(() => this.Enabled = true));
    };

    _BackgroundWorker.RunWorkerAsync();

}

Everything working correctly.But problem is butProcess_2_Click which I need to copy all code from butProcess_1_Click. And I have to change only one line to invoke process_2().

Process_2(string_param1, guid_param2, byteArray_param3, bool_param4);

I don't want to duplicate my code. What I want to do is like below.

public void GenericFunction(Function _FunctionCode)
{
    frmLoadingControl _frmLoadingControl = new frmLoadingControl();            
    _frmLoadingControl.Show(this);

    BackgroundWorker _BackgroundWorker = new BackgroundWorker();
    _BackgroundWorker.DoWork += (s, args) =>
    {
        this.Invoke(new MethodInvoker(() => this.Enabled = false));
        /// below parameters are just sample.
        //Process_1(int_param1, decimal_param2, datetime_param3);
        //Process_2(string_param1, guid_param2, byteArray_param3, bool_param4);
        Execute(_FunctionCode);
    };
    _BackgroundWorker.RunWorkerCompleted += (s, args) =>
    {
        _frmLoadingControl.Close();
        this.Invoke(new MethodInvoker(() => this.Enabled = true));
    };

    _BackgroundWorker.RunWorkerAsync();
}

private void butProcess_1_Click(...)
{
    /// below parameters are just sample.
    //Process_1(int_param1, decimal_param2, datetime_param3);
    GenericFunction(Process_1(int_param1, decimal_param2, datetime_param3));
}

private void butProcess_2_Click(...)
{
    /// below parameters are just sample.
    //Process_2(string_param1, guid_param2, byteArray_param3, bool_param4);
    GenericFunction(Process_2(string_param1, guid_param2, byteArray_param3, bool_param4));
}

Please let me get your suggestion.


Solution

  • Pass a delegate, like this:

    // CHANGE HERE
    public void GenericFunction(Action action)
    {
        frmLoadingControl _frmLoadingControl = new frmLoadingControl();            
        _frmLoadingControl.Show(this);
    
        BackgroundWorker _BackgroundWorker = new BackgroundWorker();
        _BackgroundWorker.DoWork += (s, args) =>
        {
            this.Invoke(new MethodInvoker(() => this.Enabled = false));
    
            // CHANGE HERE
            action();
    
            Execute(_FunctionCode);
        };
        _BackgroundWorker.RunWorkerCompleted += (s, args) =>
        {
            _frmLoadingControl.Close();
            this.Invoke(new MethodInvoker(() => this.Enabled = true));
        };
    
        _BackgroundWorker.RunWorkerAsync();
    }
    
    private void butProcess_1_Click(...)
    {
        // CHANGE HERE
        GenericFunction(() => Process_1(int_param1, decimal_param2, datetime_param3));
    }
    

    Shouldn't this: _frmLoadingControl.Close(); be put in the Invoke in the next row? It is something that "acts" on a "piece" of Winforms...

    this.Invoke(new MethodInvoker(() => 
    {
        _frmLoadingControl.Close();
        this.Enabled = true;
    }));