Лучший способ отменить вызов Unix (используя библиотеку SSH) через пользовательский интерфейс в синхронном приложении на C #? - PullRequest
3 голосов
/ 23 марта 2011

Моя программа (.NET 4.0) использует стороннюю библиотеку SSH ( SSH.NET , отлично работает до сих пор) для отправки команды Unix, которая построена на основе выбора пользователя в пользовательском интерфейсе, ожидаетдля отдыха и выводит его.Моя проблема возникает, когда иногда unix-ответ просто «зависает» из-за отсутствия лучшего термина, и в этом случае моя программа застревает в ожидании.В Unix вы можете просто избежать этой команды (для меня CTRL-C) и попробовать еще раз, но при использовании библиотеки я не уверен, как обеспечить эквивалент.

Другая проблема заключается в том, что поток пользовательского интерфейсазаблокирован, когда это происходит, поэтому даже если бы была какая-то кнопка «Отмена», пользователь не смог бы нажать на нее.Я посмотрел на BackgroundWorker и Threading, но на самом деле это не имеет смысла, потому что моя работа синхронная - программа должна ждать ответа, чтобы она могла его проанализировать (формат, цвет, т. Д.).

Любые мыслина это бы сильно заценил, спасибо всем!

Ответы [ 2 ]

2 голосов
/ 23 марта 2011

Я не могу говорить конкретно с SSH.NET и как вы можете отменить команду через эту библиотеку, но вот как я бы подошел к ней.

Я бы запустил «команду» для Задачи, которая по сути является отдельным потоком. Вот мой пример кода:

private Task _commandTask;
private CancellationTokenSource _cancellation;

protected void SendCommand(object sender, EventArgs e) 
{
    if(_commandTask != null)
        return; // Can't run the task twice

    _cancellation = new CancellationTokenSource();
    _commandTask = new Task(SendSshCommand, _cancellation.Token);
    _commandTask.ContinueWith(FinishCommand, TaskScheduler.FromCurrentSynchronizationContext());

    _commandTask.Start();

    // returning control to the UI thread now
}

protected void CancelCommand(object sender, EventArgs e) 
{
    if(_commandTask == null)
        return;

    _cancellation.Cancel();
}

private static void SendSshCommand() 
{
    // Send your SSH Commands here
}

private void FinishCommand(Task task) 
{
   // Update your UI here

   // remove this task
   _commandTask = null;
   _cancellation = null;
}

Таким образом, метод SendCommand будет вызываться из какого-либо события в вашем пользовательском интерфейсе (я полагаю, нажатие кнопки). Он создает CancellationTokenSource и новую Task . Эта задача вызывает метод SendSshCommand в отдельном потоке. Затем мы создаем продолжение задачи с помощью метода ContinueWith. Передача TaskScheduler.FromCurrentSyncrhonizationContext() говорит задаче продолжения, которую мы хотим выполнить в потоке пользовательского интерфейса, а не в отдельном потоке. Это важно, потому что если мы не в потоке пользовательского интерфейса, мы не можем получить доступ ни к одному из элементов управления пользовательского интерфейса.

CancelCommand будет вызван с вашей кнопки отмены, и он просто скажет _commandTask прекратить выполнение.

Теперь это не 100%, я уверен, что у вас будет состояние, которое необходимо передать задачам, и есть структуры Generic Task , которые помогут вам в этом. Кроме того, в вашем FinishCommand вы захотите проверить, чтобы задача была выполнена, не отменена и не вызвала исключение. Читайте о задачах и TPL в .Net 4, и вы увидите, как это сделать.

Стоит также отметить, что я не уверен, что произойдет с вашей библиотекой SSH.NET после отмены. Я бы предположил, что это просто отключит сеанс SSH, что в свою очередь завершит процесс на Unix-машине. Но опять же, я не знаком с этой конкретной библиотекой, поэтому вам придется провести некоторое тестирование.

Надеюсь, это поможет!

0 голосов
/ 23 марта 2011

Я не знаком с библиотекой, но если у вас есть один сеанс SSH, то есть та же оболочка, затем запустите команду в качестве фоновой задачи и отмените ее с помощью kill% 1

Запуск: -

команда &

Отмена: -

kill% 1

Это, конечно, требует, чтобы он был в одной оболочке.

CTRL-C - это ASCII 3, если у вас есть интерфейс потокового типа для отправки оболочки, который может работать.

...