C# 如何为异步任务创建一个 "UpdateGui" 方法(如何将 GUI 控件作为变量传递)?

C# How to create an "UpdateGui" Method for async tasks (how to pass GUI control as variable)?

我正在尝试弄清楚如何将 "UpdateGUI" 控件创建为线程中的方法。例如,以下代码适用于单个 GUI 对象。但我无法弄清楚如何将 RichTextBox "pingCheckStdOut" 变成一个变量来更新我程序中的任何 RichTextBox。 (预期目标是减少重复代码)。

// RichTextBox pingCheckStdOut in Form1 created by the IDE: 
this.pingCheckStdOut = new System.Windows.Forms.RichTextBox();

// my code: 
// Calling the async task from here 

private async void pingCheckInitBtn_Click(object sender, EventArgs e)
    {

        string ipAddress = pingCheckIpAddressBox.Text;
        string ldapUsername = usernameBox.Text;
        string ldapPassword = passwordBox.Text;
        string command = "";

 await Task.Run(() => sshAllStdOut(ipaddress, ldapUsername, ldapPassword, command));
    }

// the code I'm having trouble with (want to change pingCheckStdOut to a variable)

private async Task sshAllStdOut(string ipaddress, string ldapUsername, string ldapPassword, string command) 
    {
       SshClient client = new SshClient(ipaddress, 22, ldapUsername, ldapPassword);
        client.Connect();

        var stream = client.CreateShellStream("dumb", 120, 24, 360, 600, 1024);

            var reader = new StreamReader(stream);
            var writer = new StreamWriter(stream);
            writer.AutoFlush = true;

            while (stream.Length == 0)
            {
                Thread.Sleep(1000);
            }

            WriteStream(command, writer, stream);

        while (client.IsConnected)
        {

            string line = reader.ReadLine();
            if (line != null)
            {

//This is the line I'd like to convert into a "variable" for example:
// updateGUI(line, pingCheckStdOut) instead of passing directly
                updateGUI(line); 
                Thread.Sleep(100);
            }

            if (line == "server_name:~ $ ")
            {
                                    client.Disconnect();
            }


        }




    }

/* This is my code to update the GUI from the thread */

delegate void SetTextCallback(string output);

    public void updateGUI(string input)
    {

        string output = input;


        if (this.InvokeRequired)
        {
            // It's on a different thread, use Invoke.
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke
                (d, new object[] { output });
        }
        else
        {
            // Else it's on the same thread, no need for Invoke
            this.pingCheckStdOut.Text = output;
        }
    }
    // This method is passed in to the SetTextCallBack delegate
    // to set the Text property of the RichTextBox.
    public void SetText(string output)
    {
        this.pingCheckStdOut.AppendText(output + "\n");
        pingCheckStdOut.ScrollToCaret();

     }

但是,在这段代码中,我只更新了名为 "pingCheckStdOut" 的 RichTextBox 控件。我试图弄清楚如何将不同的 GUI 元素传递到此方法中。因此,如果我有另一个名为 "newProgramStdOut" 的 RichTextBox,我该如何重用这个 updateGUI() 方法?

我是一个新的 C# 程序员,来自 Perl,所以它与我以前的习惯有很大的不同。该程序的预期目标是将 SSH.Net 控制台中的所有内容实时转储到 GUI 中,以便为 Linux 框上托管的命令行脚本提供 "interface"。

已更改:

public void updateGUI(string input, RichTextBox guiElement)

this.Invoke
(d, new object[] { output, guiElement });

public void SetText(string output, RichTextBox guiElement)
    {
        guiElement.AppendText(output + "\n");
        guiElement.ScrollToCaret();


    }

完整代码:

private async Task sshAllStdOut(string ipaddress, string ldapUsername, string ldapPassword, string command) // work in progress
    {
        SshClient client = new SshClient(ipaddress, 22, ldapUsername, ldapPassword);
        client.Connect();

        var stream = client.CreateShellStream("dumb", 120, 24, 360, 600, 1024);

            var reader = new StreamReader(stream);
            var writer = new StreamWriter(stream);
            writer.AutoFlush = true;

            while (stream.Length == 0)
            {
                Thread.Sleep(1000);
            }

            WriteStream(command, writer, stream);
            Thread.Sleep(1000);
            WriteStream("\n", writer, stream);


        while (client.IsConnected)
        {

            string line = reader.ReadLine();
            if (line != null)
            {
                updateGUI(line, pingCheckStdOut);
                Thread.Sleep(100);
            }

          if (line == "server_name:~ $ ")
            {
                client.Disconnect();

            }


        }




    }

   // this is to pull the data from the 2nd thread back into the main thread
    delegate void SetTextCallback(string output, RichTextBox guiElement);

    public void updateGUI(string input, RichTextBox guiElement)
    {

        string output = input;


        if (this.InvokeRequired)
        {
            // It's on a different thread, so use Invoke.
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke
                (d, new object[] { output, guiElement });
        }
        else
        {
            // Else it's on the same thread, no need for Invoke
            guiElement.Text = output;
        }
    }
    // This method is passed in to the SetTextCallBack delegate

 public void SetText(string output, RichTextBox guiElement)
    {
        guiElement.AppendText(output + "\n");
        guiElement.ScrollToCaret();


    }