我的程序(.NET 4.0)使用第 3 方 SSH 库(SSH.NET,到目前为止效果很好)发送一个基于用户在 UI 中的选择构建的 unix 命令,等待响应并输出它。当有时 UNIX 响应由于缺乏更好的术语而“挂起”时,我的问题就出现了,在这种情况下,我的程序陷入等待。在unix中,你可以转义该命令(对我来说是CTRL-C)并重试,但是在使用库时,我不确定如何提供等效的命令。
另一个问题是,发生这种情况时 UI 线程被锁定,因此即使有某种“取消”按钮,用户也无法单击它。我研究了BackgroundWorker和Threading,但这实际上没有意义,因为我的操作是同步的——程序必须等待响应,以便它可以解析它(格式、颜色等)。
任何对此的想法都会非常感激,谢谢大家!
My program (.NET 4.0) uses a 3rd party SSH library (SSH.NET, works great so far) to send a unix command that is constructed based on the user's choices in the UI, waits for the respose and outputs it. My problem arises when sometimes the unix response just "hangs" for lack of a better term, in which cases my program is stuck waiting. In unix you can just escape that command (for me CTRL-C) and try again, but when using a library, I'm not sure how to provide the equivelent.
Another problem is that the UI thread is locked when this is happening, so even if there was some sort of "Cancel" button the user wouldn't be able to click on it. I looked into BackgroundWorker and Threading, but that doesn't really make sense because my operation is synchronous - the program has to wait for the response so it can parse it (format, color, ect).
Any thoughts on this would much appriciated, thanks all!
发布评论
评论(2)
我无法具体谈论 SSH.NET 以及如何通过该库取消命令,但以下是我的处理方法。
我会在任务上启动“命令”,这本质上是一个单独的线程。这是我的示例代码:
因此,将从 UI 上的某个事件调用
SendCommand
方法(我假设单击按钮)。它创建一个CancellationTokenSource
和一个新的 任务。此任务在单独的线程上调用SendSshCommand
方法。然后,我们使用ContinueWith
方法创建任务延续。传入TaskScheduler.FromCurrentSyncrhonizationContext()
告诉我们要在 UI 线程而不是单独的线程上执行的延续任务。这很重要,因为如果我们不在 UI 线程上,我们就无法访问任何 UI 控件。CancelCommand
将从取消按钮调用,它只是告诉_commandTask
停止执行。现在这还不是 100%,我确信您将会有需要传递给任务的状态,并且有 通用任务 结构可以帮助您完成此任务。另外,在
FinishCommand
中,您需要检查以确保任务已完成、未取消且未引发异常。阅读 .Net 4 中的任务和 TPL,您将了解如何做到这一点。还值得注意的是,我不确定取消后您的 SSH.NET 库会发生什么情况。我认为它只会断开 SSH 会话,从而结束 Unix 机器上的进程。但同样,我不熟悉那个特定的库,所以你必须做一些测试。
希望有帮助!
I can't speak specifically to the SSH.NET and how you can cancel a command via that library, but here's how I would approach it.
I would launch the "command" on a Task, which is essentially a separate thread. Here's my sample code:
So the
SendCommand
method would be invoked from some event on your UI (button click I assume). It creates aCancellationTokenSource
and a new Task. This task calls theSendSshCommand
method on a separate thread. We then create a task continuation with theContinueWith
method. Passing in theTaskScheduler.FromCurrentSyncrhonizationContext()
tells the continuation task that we want to execute on the UI's thread instead of a separate thread. This is important because if we're not on the UI thread we cannot access any of the UI controls.The
CancelCommand
would be called from your cancel button, and it simply tells the_commandTask
to stop executing.Now this isn't 100%, I'm sure you're going to have state that you need to pass around to the tasks, and there are Generic Task structures to help you with that. Also, in your
FinishCommand
, you're going to want to check to make sure the task was completed, not cancelled, and didn't throw an exception. Read up on Tasks and the TPL in .Net 4 and you'll see how to do that.It's also worth noting, that I'm not sure what will happen with your SSH.NET library after the cancellation. I would assume it would just disconnect the SSH session, which in turn would end the process on the Unix machine. But again, I'm not familiar with that particular library so you'll have to do some testing.
Hope that helps!
我对该库不熟悉,但如果您有一个 SSH 会话,即同一个 shell,则将该命令作为后台任务启动,并通过 Kill %1
Launch 取消它:-
取消:-
当然,这确实要求它位于同一个 shell 中。
如果您有一个可以工作的 shell 发送流类型接口,则 CTRL-C 是 ASCII 3。
I'm not familiar with the library but if you have one SSH session, that is, the same shell then launch the command as a background task and cancel it with a kill %1
Launch:-
Cancel:-
This does require it to be in the same shell of course.
CTRL-C is ASCII 3 if you've got a stream type interface to the shell sending that might work.