2016-09-13 8 views
0

私はJava環境から来て、ちょうどC#を学び始めました。C#バックグラウンドワーカーUIからの更新

(溶液を見て、質問の最後にスクロールしてください)

私はいくつかの計算を行うと、UIを更新するWebサービスからのいくつかのデータをフェッチするために、バックグラウンドワーカーを使用しようとしているが、私はカント進捗状況を報告するように思われる

私のForm1.ccには、自分のUIフォームを表すMainFormクラス(2つの日付ピッカー、1つのプログレスバー、ボタンが含まれています)があります。私は背景にスタッフを処理するためにすべての私のロジックを持ってAdstage.csで

private void runReport_Click(object sender, EventArgs e) 

private void runReport_Click(object sender, EventArgs e) 
     { 
      //MessageBox.Show("button pressed\n datefrom "+dateFrom.Value.ToString("yyyy-MM-dd")); 
      AdStage data=new AdStage(dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.ToString("yyyy-MM-dd")); 
      //this.progressLabel.Text = "Fetching Data From Adstage";  
      //data.setUIProgressItems(progressLabel, this.progressBar); 
      data.setUI(this); 
      data.startWorker(); 
     } 

:私は、次のクリックハンドラをバインドされているボタンを

/*constructor*/ 
     public AdStage(String dateFrom, String dateTo) 
     { 
      //set the dates 
      setDates(dateFrom, dateTo); 

     } 
     public void startWorker() 
     { 
      doBg();//start bg worker... 
     } 

     public void setUI(MainForm ui) 
     { 
      this.ui = ui; 
     } 

private void setDates(String dateFrom, String dateTo) 
     { 
      if (dateFrom.Equals(dateTo)) 
      { 
       this.dateTo = this.dateTo = dateFrom; 
      } 
      else 
      { 
       this.dateFrom = dateFrom; 
       this.dateTo = dateTo; 
      } 
     } 

private void doRequest(String offset,String url= null,BackgroundWorker worker=null,int p=0) 
    { 
    //all of the logic that gets data from the web serivces is here 
} 



private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      Console.WriteLine(String.Format("worker_runWorkerCompleted")); 
      //update ui once the job has finished.. 
      MessageBox.Show("Data Fetched! Total Campaigns: "+this.campaigns.Count()); 
      //this.ui.updateProgress("Fetched " + this.campaigns.Count() + " campaigns",100); 
      //this.ui.progressLabel.Text = "Fetched "+this.campaigns.Count()+" campaigns"; 


     } 

     public void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      Console.WriteLine("Testing worker_ProgressChanged: "+e.ProgressPercentage.ToString()); 
      MessageBox.Show("Progress: " + this.campaigns.Count()); 
      this.ui.progressLabel.Text = e.ProgressPercentage.ToString(); 
     } 

そして、これは私のDoWork関数です

private void worker_DoWork(object sender, DoWorkEventArgs e) 
      { 
       Console.WriteLine(String.Format("worker_doWork")); 
       //do all major background work here.. 
       BackgroundWorker worker = sender as BackgroundWorker; 
       worker.ReportProgress(1); 
       doRequest(offset,null,worker); 
       (worker as BackgroundWorker).ReportProgress(99, null); 
       //worker.ReportProgress(100); 
      } 

そうでもID doRequest(の内部報告書の進捗状況を使用している場合)worker_ProgressChangedが呼び出されないようにその機能。作業者は、Webサービスからすべてのページを取得し、終了時にのみレポートを返します。 決してが発生していないworker_ProgressChangedイベント..

EDIT:人々は私がやっているのか理解を助けるために自分のコードを明確に:)

私は労働者がdoBGと呼ばれる方法で作成されています();

private void doBg() 
     { 
      Console.WriteLine(String.Format("BG WORKER STARTED")); 
      this.worker.DoWork += worker_DoWork; 
      this.worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
      this.worker.WorkerReportsProgress = true; 
      worker.RunWorkerAsync(); 
     } 

buttn runReportをクリックすると、Adstageクラスのインスタンスが作成されます。 (AdStage data=new AdStage(dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.ToString("yyyy-MM-dd"));

そして、そのインスタンス上で、私はへの呼び出しを行うことでMainFormをからバックグラウンドワーカーを開始し、その後

とを(これは私はAdstageクラスからMainFormをメンバーにアクセスできるだけである)UIを設定しますdata.startWorker(); (これは基本的にAdstageクラスのdoBG()関数を呼び出すだけです)。これは、私がdoBG()をAdstageクラスでプライベートに設定したためです。

EDIT 2:doBg()関数の内部this.worker.ProgressChanged += worker_ProgressChanged;を追加 は、良いヒント:)また

にするために機械学習をのことを指摘するためにあなたにディルクに感謝し、あなたに感謝し、トリックを行うようです誰でも同じ問題がある場合は、代理人を使用してUIを更新することもできます。それを行うにはどのようにアイデアを得るために チェックここでは、この答え:https://stackoverflow.com/a/3303276/514657(それは本当に私が代表者と連携する方法を理解する助けた)

+2

あなたは 'BackgroundWorker' intializeていますが、そのプロパティを設定しているところ、私は表示されない[' WorkerReportsProgress'](https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker。 workerreportsprogress.aspx)を 'true'に変更しますか? – Dirk

+0

私はdoBG()という専用の関数の中でそれを初期化します。 Adstageクラスで – George

+0

そして 'worker_ProgressChanged'メソッドを' worker.ProgressChanged'イベントに追加したことがありますか?私は今、それが動作するはずだと思う ありがとう: – Dirk

答えて

0

は、バックグラウンドワーカーへのUIのフォームを渡すが、中ProgressChangedを記述しないでくださいUIフォーム。

また、ProgressChanged(およびRunWorkerCompleted)は、別のスレッドからUIを更新できないため、ワーカのメソッドであってはなりません。

+0

私は基本的にUIをAdstageクラスに渡します。そのクラスには、バックグラウンドワーカーを初期化するすべてのロジック+関数が含まれています。 私は、Adstageクラスのワーカーオブジェクトを取得し、そのオブジェクトをmainFormクラスの内部で使用するパブリック関数を作成する必要があると言っていますか? – George

+0

いいえAdstageクラス(あなたのバックグラウンドワーカーですか?)には、進行状況が変更されている間にバックグラウンドで実行する必要のあるDoWorkメソッドのみが含まれている必要があり、完了したメソッドは通常、 UIクラスに含まれている必要があります。 –

+0

あなたはUIでメソッドを初期化する場合は、私はつもりは後にそれを試してみるよ:) UIの方法とヒントについて –

関連する問題