【问题标题】:Close used WinSCP session when exiting application (while in use)退出应用程序时关闭使用的 WinSCP 会话(在使用中)
【发布时间】:2018-12-12 13:49:11
【问题描述】:

我有一个运行后台线程的应用程序,该线程打开一个用于执行操作的 WinSCP 会话,如下所示:

new Thread(() => {

    //do stuff
    SessionOptions options = new SessionOptions
    {
        //options
    };

    using(Session session = new Session())
    {
        bool success = false;
        foreach (var ip in IPs)
        {
            options.HostName = ip.Value;
            try
            {
                session.Open(options);
                success = true;
                break;
            }
            catch (Exception)
            {

            }
        }
        if(success)
        {
            CommandExecutionResult result = session.ExecuteCommand(*some command*);
            result.Check();
            someVariable = result.Output;
        }
    }

    //do stuff
})
{
    IsBackground = true
}.Start();

现在我注意到,如果我在using 中关闭应用程序,线程确实会停止,但 WinSCP 会话仍保持打开状态(可能是因为线程已中止?)如果我重复该过程,我当然会结束,有更多的 WinSCP 会话。如何关闭我在应用程序中打开的特定会话?

已编辑:添加了更多在 using 块中发生的事情。

【问题讨论】:

  • "会话保持打开状态"到底是什么意思?您使用的是哪个版本的 Windows?
  • 进程在TaskManager里面,就是我的意思。我使用的是 Windows 7。
  • 我已将您的代码放入 C# 控制台应用程序,并将 Thread.Sleep 添加到主线程和后台线程。如果我运行应用程序(在 Windows 7 和 10 上测试)并关闭它,或者即使我突然从任务管理器中杀死它,WinSCP 子进程也完全消失了。这是意料之中的,因为子进程在与 .NET 代码相同的 Windows job 中运行,所以无论 .NET 代码做什么,它都是一个操作系统来处理这个问题 - 所以我们需要更多细节来重现这个问题- 请发帖minimal reproducible example
  • 嘿,这样做有点困难,因为它是一个大框架的一部分,我无法访问所有内容。如果您说它通常应该可以工作,那么那里还有其他东西会破坏它。但是,我不能只用代码结束这个过程吗?
  • 这是一个相当广泛的问题。当您关闭应用程序时,会话会做什么?它是空闲的还是正在做某事?如果它正在做某事,你想让它完成吗?还是要中止它?

标签: c# .net multithreading winscp winscp-net


【解决方案1】:

您可以使用 Session.Dispose 方法杀死底层进程。

请参阅此 WinSCP 文档:https://winscp.net/eng/docs/library_session_dispose

还请注意本文中的文字:

如果会话已打开,则将其关闭,终止底层 WinSCP 进程,删除 XML 日志文件并释放对象。

与 Session.Close 不同,之后无法重用该对象。

【讨论】:

  • 当然可以,但是如何访问该对象?无论如何都应该使用 using 来处理它,但是线程是后台的,因此它被主线程终止,并且它内部的 catch 似乎没有做任何事情。
【解决方案2】:

我已将您的代码放入 C# 控制台应用程序,并将 Thread.Sleep 添加到主线程和后台线程。如果我运行应用程序(在 Windows 7 和 10 上测试)并关闭它,或者即使我突然从任务管理器中杀死它,WinSCP 子进程也完全消失了。

这是意料之中的,因为子进程在与 .NET 代码相同的 Windows job 中运行。因此,无论 .NET 代码做什么,它都是一个负责清理 WinSCP 子进程的操作系统。所以你的应用程序中发生了一些奇怪的事情。


无论如何,如果您想确保 WinSCP 会话被中止,只需在关闭应用程序时从主线程调用 Session.Abort

【讨论】:

    【解决方案3】:

    我的解决方案,在 Form_FormClosing 事件处理程序上,只需输入以下几行:

                foreach (var process in Process.GetProcessesByName("WinSCP"))
                {
                    process.Kill();
                }
                (Process.GetCurrentProcess()).Kill();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-29
      • 2013-03-15
      • 1970-01-01
      • 1970-01-01
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多