2

そのデータをwinformに表示するためにx秒間隔ごとにデータベースからデータを取得するデスクトップアプリケーションを構築しています.GUIをブロックしたくありません.データを取得するメソッドに時間がかかるかどうかは気にしません.チェック間隔、GUI とは非同期のメソッドが必要です。最適なアプローチは何ですか?またその理由は何ですか? スレッドの初心者に感謝します!

バックグラウンドワーカー?スレッドスリープ? 手動リセットイベント?

4

2 に答える 2

2

したがって、X 秒ごとにタスクを実行したいと言うことから始めます。これは、タイマーが必要であることを示しています。ただし、選択できるものはたくさんあります。 System.Timer私たちの目的には問題なく動作するはずですが、使用したい場合は使用System.Windows.Forms.Timerできます。フォームを開いたときにタイマーを開始し、間隔を希望どおりに構成し、タイマーが起動したときに実行するハンドラーを割り当てます。

次に、タイマーが起動したら、データベース呼び出しを実行して UI を更新する必要があります。長時間実行される操作を実行し、結果を使用して UI を更新することは、このBackgroundWorkerクラスが目的に合わせて作成されたものです。DoWorkデータベース呼び出しを行うメソッドを設定WorkerCompletedし、結果に基づいてイベントで UI を更新します。(完了イベントは UI スレッドで自動的に実行されます。そのスレッドに手動でマーシャリングする必要はありません。)

十分に新しいバージョンの C# を使用している場合は、Tasks を使用してこれらと同じことを行うこともできます。Task.Factory.StartNewデータベース呼び出しに使用してバックグラウンド スレッドで実行することができます。その後ContinueWith、それが返されたときに呼び出してTask、同期コンテキストを指定できるオーバーロードを使用できます。簡単な例を次に示します。

private void handler(object sender, EventArgs e)
{
    Task.Factory.StartNew(() => getInfoFromDB())
        .ContinueWith(task => label1.Text = task.Result,
        CancellationToken.None, TaskContinuationOptions.None,
        TaskScheduler.FromCurrentSynchronizationContext());
}

private string getInfoFromDB()
{
    Thread.Sleep(2000);//simulate long IO operation
    return "Hello world!";
}

このベースの例を機能させるには、タイマーを使用して、ティック イベントが UI スレッドで実行されるようにTaskする必要があることに注意してください。System.Windows.Forms.Timer

于 2012-10-15T16:53:51.910 に答える
0

Kamil が指摘したようTasksに、.NET 4.0 より古いバージョンでは使用できません。

暗黒時代に行き詰まっている場合、BackgroundWorker はこれをうまく処理します。実際、これはおそらくそのために作成されたものです。

テストされていない疑似コード:

public partial class Form1 : Form {

  private bool ok;
  private BackgroundWorker worker;

  public Form1() {
    InitializeComponent();
    worker = new BackgroundWorker();
    worker.WorkerReportsProgress = true;
    worker.WorkerSupportsCancellation = true;
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    ok = true;
  }

  private void timerTick(object sender, EventArgs e) {
    if (!worker.IsBusy) {
      worker.RunWorkerAsync();
    }
  }

  private void worker_DoWork(object sender, DoWorkEventArgs e) {
    var w = (BackgroundWorker)sender;
    MyData inputData = (MyData)e.Argument;
    for (int i = 0; (i < NUM_TASKS) && !worker.CancellationPending; i++) {
      w.ReportProgress(i);
      // do tasks
    }
    e.Result = SomethingYouWantReturned();
  }

  private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
    if (!ok) {
      worker.CancelAsync();
    }
  }

  private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    if (e.Error != null) {
      ok = false;
      MessageBox.Show(this, e.Error.Message, "Error!");
    } else {
      var item = (TypeYouWantedReturned)e.Result;
      Console.WriteLine("Do something with `item`.");
    }
  }

}
于 2012-10-15T18:03:52.770 に答える