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

时间:2009-07-28 13:33:15

标签: c# windows-services ftp backgroundworker

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

#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文件提取。

1 个答案:

答案 0 :(得分:2)

BackgroundWorker通过将某个任务分离到独立于调用应用程序的单独后台线程上来工作。后台工作程序的生命周期遵循以下模式:

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

要提供有关原始问题的建议,似乎您要做的是将后台工作者标记为支持取消(bgw.WorkerSupportsCancellation = true)并让您的stop事件调用BackgroundWorker上的CancelAsync()方法。更新您的DoWork方法,以便在适当的时间点轮询“CancellationPending”属性,并在发生故障时执行取消,使您的服务处于已知状态。