4


2

データベースの周期的なポーリングのためのC#タイマー

私はこれまでC#にあまり馴染みがありませんでした。少なくとも最初に何かをする方法を選択するときに自信を持てないほどです。

コントロールの更新のために、WPFアプリケーションからのSQL Serverデータベースタイマーベースのポーリングを整理する最良の方法は何でしょうか。

この問題についての考えを共有していただけますか、それとも実装方法をコード例を示してください。 そのようなポーリングの期間を設定することは、どの程度短い(または合理的)ですか? 危険なことは何ですか?

たぶんこれを行うための1つの標準的で正しい方法がありますか?

3 Answer


4


SqlDependencyオブジェクトを使用できますが、これは実装をSQL Server 2005+と密接に結び付けます。


2


アプリケーション全体の更新が必要で、更新の遅延があまり大きくない場合、最良のオプションは、データが更新されたサブスクライバーにイベントを実行および投稿できるバックグラウンドの「スレッド」を開始することです(イベントにカスタムの `EventArgs`を追加して、特定のロジックを使用して変更されているかどうかを最初に確認してください)。

たとえば、このクラスのインスタンスをトップレベルのどこかに作成します(おそらくメインフォームコードですか?)。

using System;
using System.Threading;
using System.Windows.Forms;

public class PollerThread
{
    private Thread _thread;
    private SynchronizationContext _syncContext;

    public event EventHandler UpdateFinished;

    public PollerThread()
    {
        _syncContext = WindowsFormsSynchronizationContext.Current;

        ThreadStart threadStart = new ThreadStart(ThreadStartMethod);
        _thread = new Thread(threadStart);
        _thread.Name = "UpdateThread";
        _thread.IsBackground = true;
        _thread.Priority = System.Threading.ThreadPriority.Normal;
    }

    public void Start()
    {
        if ((_thread.ThreadState & ThreadState.Unstarted) == ThreadState.Unstarted)
            _thread.Start();
        else
            throw new Exception("Thread has already been started and may have completed already.");
    }

    public void ThreadStartMethod()
    {
        try
        {
            while (true)
            {
                // Go get the new data from the SQL server

                OnUpdateFinished(); // Notify all subscribers (on their own threads)
                Thread.Sleep(10000); // 10 sec wait before the next update
            }
        }
        catch (ThreadAbortException)
        {
            // The thread was aborted... ignore this exception if it's safe to do so
        }
    }

    protected virtual void OnUpdateFinished()
    {
        if (UpdateFinished != null)
        {
            SendOrPostCallback method = new SendOrPostCallback(
            delegate(object state)
            {
                UpdateFinished(this, EventArgs.Empty);
            });
            _syncContext.Send(method, null);
        }
    }
}

`UpdateFinished`イベントへの新しい更新に応答する必要がある各エリアをサブスクライブします。 これは、 `PollerThread`クラスを構築するために使用されるスレッドで実行されます。

この答えは少し緩いように聞こえるかもしれませんし、より具体的にはwindowsフォームプロジェクトに適用されますが、有用性は実際に現在の実装に依存します。 とにかくこれで構築できます。 それが役に立てば幸い :)


1


要件は非常に一般的に説明されているため、一般化でのみ対応できます。

一般に

  1. 同時にポーリングするアプリケーションの数は?

  2. 結果セットの大きさは?

10人のクライアントはそれほど多くありませんが、1万人はそうです。 10行は小さく、1000行は大きくて遅くなります。 これらの質問に答えることで、ポーリング頻度を設定する方法がわかります。

最も効率的で効果的な設計を決定するには、UIの応答性(非同期でデータを更新する)、新しいデータの必要性、データベースが更新される頻度に関する知識など、他の考慮事項のバランスを取る必要があります。