2009-07-28 18 views
0

基本的には、BackgroundWorkerコンポーネントの助けを借りてファイルをFTPの場所から取り出して、そこでスレッドの安全性を保証する簡単なデーモンを実装し始めています。私は正しい方向に向かっていると感じていますが、関連する技術に完全に精通しているわけではないので、アプリケーションのライフサイクル全体ではあまり簡単ではありません。たとえば、処理方法がわからないシナリオがありますまだ、すなわち、ストップイベントで何をすべきか、ワーカーが走っている間にサービスが停止されるとどうなるでしょうか?私は、次のコードは達成しようとしていることをほとんど意味していないと思います。Windows上でデーモンを取得するスレッドセーフな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ファイルのフェッチを再実装しました。

+0

少し質問を明確にする必要があります。 Windowsサービスのライフサイクルについて質問していますか? FTPクライアントライブラリの作成方法についてスレッドについて?このシナリオに対するBackgroundWorkerの適用性について –

+0

こんにちはVinko、あなたのコメントのために多くの感謝!私がしようとしているのは、Windows用のスレッドセーフなFTPファイルフェッチャーデーモンです。これは良い解決策だと思っていましたが、実際にはより良いアプローチを提案することをためらっていません! –

答えて

2

BackgroundWorkerは、呼び出し元のアプリケーションとは別の独立したバックグラウンドスレッドにタスクをスピンオフすることによって機能します。バックグラウンドワーカーのライフサイクルは、パターンは以下:

  • は、バックグラウンドワーカーを作成する(つまり、BackgroundWorkerのBGW =新...)
  • コールbgw.RunWorkerAsync A別々のバックグラウンドスレッドがBackgroundWorkerのとDoWorkによって開始され
  • メソッドはこのスレッドで呼び出されます
  • bgw.ReportProgress()を呼び出して呼び出され、BackgroundWorkers親スレッドで購読されている(および実行されている)オプションの通知イベントが発生しました
  • オプションの取り消しが発生することがあります。 bgw.CancelAsync()が呼び出されました。この呼び出しは、BackgroundWorkerオブジェクトへのアクセス権を持つ任意のスレッドから取得できます。
  • BackgroundWorker DoWorkメソッドは、自然終了または異常終了(DoWorkメソッドで未処理の例外が発生したため)によって終了します。 - RunWorkerCompletedこの方法は、あなたの元の質問にアドバイスを提供するために

を起動され、あなたがやりたいことはキャンセル(bgw.WorkerSupportsCancellation = true)をサポートするようBackgroundWorkerのフラグであるようだし、あなたの停止イベントは、CancelAsync()メソッドを呼び出していBackgroundWorkerで。 DoWorkメソッドを更新して、適切な接続点で「CancellationPending」プロパティをポーリングし、サービスが既知の状態になったときにキャンセルを実行します。

+0

Wolfwyrd、こんなに精巧な説明をしてくれてありがとう!間違いなく有益でした。 –

+0

this.transferBackgroundWorker.WorkerSupportsCancellation = trueを追加しました。私がまだ理解していないOnStopメソッドでの適切な取り消し呼び出しは、CancellationPendingプロパティがどこでどのようにチェックされるべきかです。 –

+0

チェックは、タスクの次のステップを実行するたびに、DoWorkの個別のステップごとに実行して、取り消すべきかどうかを確認してください。たとえば、あなたのFTPコールがファイルの一連のチャンクを取得することによって動作する場合、あなたのメソッドでは、(疑似スタイル)を使用します:while(BlocksLeft){if(!CancellationPending)GetNextChunk(); else AbortAndCleanup(); }。アイデアはDoWorkプロセスの次のステップを実行し、正常に取り消しを処理する直前にチェックしています。 – Wolfwyrd

関連する問題