0

我开始实现一个简单的守护进程,它基本上在 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 文件获取。

4

1 回答 1

2

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

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

为了就您的原始问题提供建议,您似乎想要将后台工作人员标记为支持取消 (bgw.WorkerSupportsCancellation = true),并让您的停止事件调用 BackgroundWorker 上的 CancelAsync() 方法。更新您的 DoWork 方法以在适当的时刻轮询“CancellationPending”属性,并在它发生时执行取消,使您的服务处于已知状态。

于 2009-07-28T14:10:32.410 回答