elunaery
elunaery

Reputation: 79

c# Using an action from GUI while running thread

Question :

I'm a beginner in c# and i'm having a bit of trouble to understand how thread works with a form. I'm trying to update a progressbar when my program hit keypoints and i can't get it to work here is my code.

For my "worker" class :

public void addFollower(string followerName, Action<string> followerAction) {
        this.followers.Add(followerName, followerAction);
    }
private void notifyFollowers(string message) {
    if (followers.Count > 0) {
        foreach (String followerName in followers.Keys) {
            followers[followerName].Invoke(message); 
        }
    }
}

for my linking class (controller maybe?) :

public void runWithParams(Dictionary<string,string> parameters, Action<string> updateManager = null){
        string app = parameters["appName"];
        string navigator = parameters["navigatorName"];
        string mode = parameters["mode"];
        string scenario = parameters["scenarioName"];
        try {
            Scenario sc = this.scenarioBuilders[app].buildScenario(scenario);
            if(updateManager != null) sc.addFollower("updateManager", updateManager);
            Thread TestRunner = new Thread(sc.run);
            TestRunner.Start();
        } catch (Exception ex) {
            Console.WriteLine(ex.Message);
            Console.WriteLine("Unexpected shutdown or driver unreachable");
        }
}

For the gui :

private void ButtonRun_Click(object sender, EventArgs e) {
        Dictionary<string, string> parameters = new Dictionary<string, string>{
            {"appName",this.CBApplicationChoice.SelectedItem.ToString()},
            {"navigatorName",this.CBNavigatorChoice.SelectedItem.ToString()},
            {"mode",this.CBModeChoice.SelectedItem.ToString()},
            {"scenarioName",this.CBScenarioChoice.SelectedItem.ToString()}
        };
        this.dispatcher.runWithParams(parameters, ManageRealTimeStep1);
    }

    public void ManageRealTimeStep1(string liveevent){
        if (liveevent.Contains("NumberOfPages")) {
            this.PBStep1.Maximum = Convert.ToInt32(liveevent.Split(':')[1]);
        } else if (liveevent.Contains("StartingTestNewPage")) {
            this.PBStep1.Increment(1);
        }
    }

I'm getting an InvalidOperationException when i click on the RunButton and the error says that i'm trying to call a function that is in another thread. How can i fix it?

Thanks in advance for any answer/ insights

Solution :

I changed the method in gui for :

public void ManageRealTimeStep1(string liveevent) {
        BeginInvoke(new Action(() => {
            if (liveevent.Contains("NumberOfPages")) {
                this.PBStep1.Maximum = Convert.ToInt32(liveevent.Split(':')[1]);
            } else if (liveevent.Contains("StartingTestNewPage")) {
                this.PBStep1.Increment(1);
            }
        }));
}

Upvotes: 0

Views: 52

Answers (2)

Anthony
Anthony

Reputation: 9571

You are not allowed to update the GUI from a different thread, see How to update the GUI from another thread in C#?.

You are accessing the GUI from the ManageRealTimeStep1 method which is used by the Scenario class (as a callback) on the background thread.

Upvotes: 0

Pavel Krymets
Pavel Krymets

Reputation: 6293

Use BeginInvoke method:

BeginInvoke(new Action(() =>
{
   this.PBStep1.Maximum = Convert.ToInt32(liveevent.Split(':')[1]);
}));

Read more about updating WinForms UI from another thread here

Upvotes: 1

Related Questions