David Mordigal
David Mordigal

Reputation: 409

Invoke delegate method name with parameter

Trying to have a setup where I have a BackgroundWorker running behind the scenes, and then updating its progress on a separate modal dialog as it completes each step. The problem is, of course, that trying to update the progress dialog from the BackgroundWorker thread causes cross-thread issues.

Code: (problematic lines have comments surrounded with ***)

public void StartProcess()
{
    // dialog that shows a simple marquee progress bar and a message
    ProgressDialog progress = new ProgressDialog("Starting operation...");

    // create background worker thread
    BackgroundWorker bw = new BackgroundWorker();
    bw.WorkerSupportsCancellation = true;
    bw.WorkerReportsProgress = true;
    bw.DoWork += Bw_DoWork;
    bw.RunWorkerCompleted += Bw_RunWorkerCompleted;

    if(!bw.IsBusy)
    {
        bw.RunWorkerAsync();
        progress.ShowDialog();
    }
}

private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker bw = sender as BackgroundWorker;
    if(bw.CancellationPending)
    {
        e.Cancel = true;
    }
    else
    {
        // perform step 1

        // *** this line generates cross-thread problems ***
        progress.Message = "Performing step 2...";

        // etc...
    }
}

And here's the code for the progress dialog:

public partial class ProgressDialog : Form
{
    public string Message
    {
        get
        {
            return lblMessage.Text;
        }
        set
        {
            if(lblMessage.InvokeRequired)
            {
                // *** not sure how to invoke this by passing the "value" parameter ***
                // *** returns a TargetParameterCountException ***
                // *** trying to pass "value" in results in "Method name expected" error ***
                lblMessage.Invoke(new UpdateMessageDelegate(SetMessage));
            }
        }
    }

    private delegate void UpdateMessageDelegate(string s);

    private void SetMessage(string s)
    {
        lblMessage.Text = s;
    }
}

How can I safely change the text value of the label by using its set method and the implicit value parameter?

Upvotes: 3

Views: 7879

Answers (2)

David Mordigal
David Mordigal

Reputation: 409

Just found one way to do it:

public string Message
{
    get
    {
        return lblMessage.Text;
    }
    set
    {
        if(lblMessage.InvokeRequired)
        {
            lblMessage.Invoke(new UpdateMessageDelegate(SetMessage), value);
        }
    }
}

Upvotes: 2

Enigmativity
Enigmativity

Reputation: 117064

Try calling it this way:

lblMessage.Invoke((Action)(() => SetMessage(value)));

Then you can also avoid creating the private UpdateMessageDelegate delegate.

Upvotes: 3

Related Questions