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();
}
我正在尝试弄清楚如何将 "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();
}