Вы должны войти, чтобы создавать сообщения и темы.

Вопрос по С#: Как отсоединится от SSH, что работает в потоке

Всем здравствуйте. Прошу помощи для выхода из тупика. Суть его вот в чем. Я пишу VNC-клиен, однако топология сети такая, что приходится сначала пробрасывать порт через SSH, а уже потом подсоединяться к локалхосту. Для VNC я использую библиотеку vncsharp, а для SSH - Renci.sshnet. В потоке я запускаю метот, который одновременно рисует контролы, создает соединение SSH и VNC. Как теперь залезть в этот поток(или грохнуть его вовсе), чтоб отсоединиться от SSH и освободить порт. От VNC я освобождаюсь перебирая контролы в панеле на форме и сравниваю их тэги, но у ssh нет контрола, по этому такой вопрос. Может я туплю и подход неверный?

Ниже код метода который пробрасывает порт и подключается к VNC

private  void VNCConnect(string shop, string pc)
{
    VncSharp.RemoteDesktop remoteDesktop = new VncSharp.RemoteDesktop();
    Parallel.Invoke(
        ()=> 
        {
            BeginInvoke((MethodInvoker)(
                () => 
                {
                    GetShopSettings(shop, pc, out string IPSSH, out string IPConnect, out string SSHLogin, out string SSHPass, out string VNCPass);//Тут я выполняю SQL процедурку и получаю настройки ПК к которому буду подключаться
                    
                    if (IPSSH != "" && IPConnect != "")
                    {
                        AuthenticationMethod auth = new PasswordAuthenticationMethod(SSHLogin, SSHPass);
                        ConnectionInfo coninfo = new ConnectionInfo(IPSSH, 22, SSHLogin, sysips.Contains(IPConnect.Substring(0, IPConnect.LastIndexOf("."))) ? ProxyTypes.None : ProxyTypes.Http, "IP-proxy", 3128, "login", "pass", auth);//Если я нахожусь в одной подсети с хостом, к которому подключаюсь, но не использовать прокси, иначе использовать

                        SshClient sshclient = PingHost(IPSSH) ? new SshClient(IPSSH, 22, SSHLogin, SSHPass) : new SshClient(coninfo); // Если конечный хост пингуется, то подключиться без прокси, иначе через предыдущий метод(Сильно замудрено, в дальнейшем упростить)
                        
                        try
                        {
                            sshclient.Connect();
                        }
                        catch (Exception ex)
                        {
                            if (sysips.Contains("10.21."))
                            {
                                if (PingHost("10.21.200.52"))//Если я в одной подсети с прокси-сервером и он пингуется, то хост недоступен
                                    frmMessageBox.Show("Не могу подключиться к хосту", "Хост недоступен \n" + ex.Message, "important"); //Создал кастомную форму с классом Show
                                else
                                    frmMessageBox.Show("Не могу подключиться к прокси", "Прокси-сервер недоступен \n" + ex.Message, "important");
                            }
                            frmMessageBox.Show("Не могу подключиться к хосту", "Хост недоступен \n" + ex.Message, "important");
                            return;
                        }
                        int tunelport = 5900;
                        while (tunelport < 5950)//Пробую пробросить порт VNC, если не получается - инкрементирую порт на 1 и пробую повторно
                        {
                            var portvnc = new ForwardedPortLocal("127.0.0.1", (uint)tunelport, "127.0.0.1", 5900);
                            sshclient.AddForwardedPort(portvnc);
                            try
                            {
                                portvnc.Start();
                                break;
                            }
                            catch (Exception)
                            {
                                sshclient.RemoveForwardedPort(portvnc);
                                portvnc.Dispose();
                                tunelport++;
                            }
                            if (tunelport == 5950)
                                {
                                        frmMessageBox.Show("Не могу подключиться", "К сожалению все порты заняты.\n" +
                                                           "Попробуйте закрыть одно из соединений к этому магазину", "info");
                                        return;
                                }
                        }
                        remoteDesktop.GetPassword = new VncSharp.AuthenticateDelegate(() => VNCPass);
                        remoteDesktop.VncPort = tunelport;
                        remoteDesktop.Connect("127.0.0.1", false, true);//Порт проброшен - подключаемся к себе через проброшеный порт
                    }
                }));
        },
        ()=>
        {//Рисую VNC клиент
            BeginInvoke((MethodInvoker)(
                () => 
                {
                    remoteDesktop.Dock = DockStyle.Fill;
                    remoteDesktop.Tag = $"{shop},{pc}";
                    pnlMain.Controls.Add(remoteDesktop);
                    remoteDesktop.BringToFront();
                }));
            
        },
        ()=> 
        {
            BeginInvoke((MethodInvoker)(
                () =>
                {//
                    Guna.UI2.WinForms.Guna2Button btnTab = new Guna.UI2.WinForms.Guna2Button
                    {
                        Dock = DockStyle.Left,
                        FillColor = System.Drawing.Color.FromArgb(139, 152, 166),
                        BackColor = System.Drawing.Color.FromArgb(139, 152, 166),
                        Text = $"{shop},{pc}",
                        Tag = $"{shop},{pc}",
                        Font = new System.Drawing.Font(Font.FontFamily, 10, System.Drawing.FontStyle.Bold),
                        BorderColor = System.Drawing.Color.DimGray,
                        BorderThickness = 1
                    };
                    btnTab.Click += tab_Click;//При нажатии контрол VNC-клиента выводится на передний план
                    btnTab.MouseClick += tab_Click_Right; //Если нажата средняя кнопка мыши, то окно закрывается(Тут и нужно организовать освобождение всех ресурсов(SSH и VNC))

                    pnlTabs.Controls.Add(btnTab);
                }));
            
        });
}


Так выглядит метод обработки нажатия средней кнопки мыши

private void tab_Click_Right(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
            {//Пока разделил на два цикла для наглядности
                Parallel.Invoke(
                    ()=> 
                    {
                        BeginInvoke((MethodInvoker)(
                            () => 
                            {
                                foreach (VncSharp.RemoteDesktop rd in pnlMain.Controls.OfType<VncSharp.RemoteDesktop>())
                                {
                                    if (rd.Tag.ToString() == ((Control)sender).Tag.ToString())
                                    {
                                        
                                        rd.Disconnect();
                                        rd.Dispose();
                                        pnlMain.Controls.Remove(rd);
                                        return;
                                    }
                                }
                            }));
                        
                    },
                    ()=> 
                    {
                        BeginInvoke((MethodInvoker)(
                            () => 
                            {
                                foreach (Guna.UI2.WinForms.Guna2Button btn in pnlTabs.Controls.OfType<Guna.UI2.WinForms.Guna2Button>())
                                {
                                    if (btn.Tag.ToString() == ((Control)sender).Tag.ToString())
                                    {
                                        
                                        btn.Dispose();
                                        pnlTabs.Controls.Remove(btn);
                                        return;
                                    }
                                }
                            }));
                    });
                
            }


Ну и сами методы запуска задачи

private  void btnVNC_Click(object sender, EventArgs e)
       {//Если уже есть вкладка с таким именем, то не подключаемся(в дальнейшем вывести на передний план)
           foreach (Guna.UI2.WinForms.Guna2Button btn in pnlTabs.Controls.OfType<Guna.UI2.WinForms.Guna2Button>())
               if (btn.Text.ToString() == $"{cbShopList.Text},{cbCashList.Text}")
                   return;

           if (cbShopList.Text == "Магазин:")
               return;
           //BeginInvoke((MethodInvoker)(() => VNCConnect(cbShopList.Text, cbCashList.Text)));
           AsyncVNCConnect();    
       }

       private async void AsyncVNCConnect()
       {
           await Task.Run(
               () =>
               {
                   BeginInvoke((MethodInvoker)(
                       () =>
                       {
                           VNCConnect(cbShopList.Text, cbCashList.Text);
                       }));

               });
               
       }