我正在开发一个程序,该程序应该与远程Linux服务器建立“n”许多SSH连接,并在每个连接上运行耗时的命令。 “耗时的操作”基本上是运行一个脚本来设置Wireshark并监听流量。
为此,我将SharpSSH库用于C#,将许多BackgroundWorkers用作线程。同样为简单起见,下面的代码有n = 2个BGW线程和SSH连接。
代码:
// runs when start is pressed
private void startButton_Click_1(object sender, EventArgs e)
{
sb = new StringBuilder();
DateTime timeNow = DateTime.Now;
clickTime = timeNow.ToString("yyyyMMddhhmmssfff"); // store the exact time of the click
bw = bwArray[0];
int index = 0; // ignore these 2 constants
foreach (BackgroundWorker bgw in bwArray)
{
if (bgw.IsBusy != true)
{
bgw.RunWorkerAsync();
// runWorkerAsync for every BackgroundWorker in the array
//index++;
}
}
}
// runWorkerAsync leads the BGWorker to this function
private void bw_doWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (worker.CancellationPending == true)
{
e.Cancel = true;
}
else
{
// let the UI know of button changes
int p = 0;
object param = "something"; // use this to pass any additional parameter back to the UI
worker.ReportProgress(p, param);
// UI notifying part ends here
// for the simplex case
if (numberOfConnections == 1)
startOperation();
// for the multiplex case
else if (numberOfConnections > 1)
{
//while (p < numberOfConnections)
//{
multiStartOperation();
// p++;
//}
}
Thread.Sleep(500);
}
}
// will be called for all ssh connections (in multiplex case)
private void multiStartOperation()
{
string[] command1Array = { "host2", "host2" };
string[] command2Array = { clickTime + "_h2", clickTime + "_h2" };
for (int index = 0; index < numberOfConnections; index++)
{
// shellArray is an array of SshExec objects
shellArray[index] = new SshExec(IPAddress, username, password);
try
{
shellArray[index].Connect();
}
catch (JSchException se)
{
Console.Write(se.StackTrace);
System.Windows.Forms.MessageBox.Show("Couldn't connect to the specified port.", "Connection Error!");
}
sb.Append(shellArray[index].RunCommand(command1Array[index]) + Environment.NewLine);
// first command is host3, or host4 etc.
// below is the time consuming command to run
string command = "./logcap.sh -c " + command2Array[index] + " -z";
// sb is a global stringBuilder object,
// to which the command output is appended
sb.Append(shellArray[index].RunCommand(command));
}
}
我的问题如下:
当我按下GUI上的开始按钮时,两个连接都应该启动并运行脚本。而在上面给出的代码中,shellArray的第一个索引(由SshExec对象组成)连接起来,准备命令并运行耗时的命令,此时程序返回到UI,甚至没有启动第二个连接。这显然是因为for循环,但我还无法弄清楚如何解决这个问题。
我需要让其他后台工作者与第二台服务器建立并运行第二个命令,这样当我按下GUI上的停止按钮时,所有连接和线程都可以一起停止。
PS:除非用户点击停止,否则命令不会停止运行,停止会向服务器发送Ctrl-C信号。
我对所有多线程和网络概念都比较陌生,所以如果有任何混淆或错误,请告诉我。
度过愉快的一天。
答案 0 :(得分:0)
感谢您的回答和欢迎。 :) 问题确实无法同时运行多个背景工作者。
我设法解决了这个问题。事实证明,我必须弄清楚的是如何将后台工作者分配给SSH连接。为此,我创建了一个类,如下所示:
class BGW
{
private BackgroundWorker bgw;
private int index;
//getters, setters, constructors...
}
在此之后,我将bwArray(一个BackgroundWorkers数组)转换为一个BGW对象数组。在初始化时,我为每个BGW对象分配了一个索引。
我没有在multiStartOperation()中使用愚蠢的循环,而是向multiStartOperation()发送了一个整数参数,该函数使用该索引来到达分配的后台工作者。
到目前为止似乎有效。 祝你有愉快的一天。