C# 在Windows上实现线程安全的FTP文件获取守护程序

C# 在Windows上实现线程安全的FTP文件获取守护程序,c#,windows-services,ftp,backgroundworker,C#,Windows Services,Ftp,Backgroundworker,我开始实现一个简单的守护程序,它基本上是在BackgroundWorker组件的帮助下从FTP位置获取文件,以保证那里的线程安全。虽然我觉得我正朝着正确的方向前进,但我并不完全熟悉所涉及的技术,因此对整个应用程序生命周期不太放心,比如说,有些场景我确实不知道如何处理,即如何处理停止事件,如果在worker运行时停止服务会发生什么,等等。我想下面的代码仅仅代表了我想要实现的目标: #region Daemon Events protected override void OnStart(strin

我开始实现一个简单的守护程序,它基本上是在BackgroundWorker组件的帮助下从FTP位置获取文件,以保证那里的线程安全。虽然我觉得我正朝着正确的方向前进,但我并不完全熟悉所涉及的技术,因此对整个应用程序生命周期不太放心,比如说,有些场景我确实不知道如何处理,即如何处理停止事件,如果在worker运行时停止服务会发生什么,等等。我想下面的代码仅仅代表了我想要实现的目标:

#region Daemon Events
protected override void OnStart(string[] args)
{
    this.transferBackgroundWorker.RunWorkerAsync();
}

protected override void OnStop()
{
            this.transferBackgroundWorker.CancelAsync(); // Thanks Wolfwyrd!
}
#endregion

#region BackgroundWorker Events
    private void transferBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        worker.WorkerSupportsCancellation = true;

        #region FTP Download

        FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(Daemon.FTP_HOST);
        ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
        ftpRequest.Credentials = new NetworkCredential(Daemon.FTP_USER, Daemon.FTP_PASS);
        FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();

        using(Stream ftpResponseStream = ftpResponse.GetResponseStream())
        {
            using (StreamWriter sw = File.CreateText(FILE_NAME))
            {
                sw.WriteLine(ftpResponseStream);
                sw.Close();
            }
            ftpResponse.Close();
        }
        #endregion

        e.Result = "DEBUG: Download complete" + ftpResponse.StatusDescription;
    }

private void transferBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        EventLog.WriteEntry("Exception caught: " + e.Error.Message);
    }
    else
    {
        EventLog.WriteEntry(e.Result.ToString());
    }
}
#endregion
任何建议都将不胜感激。非常感谢您的帮助


编辑:刚刚重新实现了FTP文件获取。

后台工作人员将一些任务拆分到独立于调用应用程序的单独后台线程上。后台工作程序的生命周期遵循以下模式:

  • 创建后台工作人员(即BackgroundWorker bgw=new…)
  • 调用bgw.RunWorkerAsync BackgroundWorker启动一个单独的后台线程,并在此线程上调用DoWork方法
  • 会引发可选的通知事件,这些事件通过调用bgw.ReportProgress()引发,并在BackgroundWorkers父线程中订阅(并对其采取行动)
  • 可能会发生可选的取消,这是在调用bgw.CancelAsync()时发生的。此调用可能来自任何可以访问BackgroundWorker对象的线程。您可以通过检查DoWork方法中的CancellationPending属性来兑现取消
  • BackgroundWorker DoWork方法通过自然完成或由于异常终止(即DoWork方法中发生未处理的异常)来完成调用-RunWorkerCompleted方法

为了对您最初的问题提供建议,您似乎想做的是将backgroundworker标记为支持取消(bgw.WorkerSupportsCancellation=true),并让停止事件调用backgroundworker上的CancelAsync()方法。更新您的DoWork方法,以便在适当的时机轮询“CancellationPending”属性,并在您的服务处于已知状态时执行取消操作。

Wolfwyrd,非常感谢您的详细解释!它确实提供了信息。我添加了this.transferBackgroundWorker.WorkerSupportsCancellation=true;在OnStop方法中正确的取消调用,我仍然不太理解的是,我应该在哪里/如何检查CancellationPending属性。检查应该在DoWork中的每个离散步骤进行,每次您准备执行任务中的下一步时,检查是否应该取消。例如,如果您的FTP调用通过获取一系列文件块来工作,那么在您的方法中,您将使用(伪样式):while(BlocksLeft){if(!CancellationPending)GetNextChunk();else AbortAndCleanup();}。你的想法是,在你做嫁妆流程的下一步之前检查一下,然后优雅地处理取消。你应该澄清一下你的问题。您是否在询问Windows服务的生命周期?关于如何编写FTP客户端库?关于线程?关于BackgroundWorker对这个场景的适用性?嘿,Vinko,非常感谢你的评论!我想做的是为windows开发一个线程安全的FTP文件获取程序守护进程,我认为这是一个很好的解决方案,但请毫不犹豫地推荐一个更好的方法!