0

複数のデバイスからデータを収集し、そのデータをローカルの SQLite データベースに保存する Windows フォーム アプリケーションがあります。次に、一定期間、新しいレコードを外部 Web サービスにアップロードする必要があります。つまり、「WasUploaded = 0」フィールドで新しいレコードを読み取り、アップロードしてから、成功時に「WasUploaded = 1」を設定する必要があります。今日、私はこれを 10 年前と同じ方法で行います。新しいバックグラウンド スレッドをフォークし、エンドレス サイクルを実行します。

while(true) 
{
   try
   {
        var newRecords = dbRepo.ReadNew(10);    // read 10 records at a time
        UploadToExternalWebservice(newRecords);
        foreach (var r in newRecords)
        {
            r.WasUploaded = 1;
        }
        dbRepo.CommitChanges(newRecords);
    } 
    catch (Exception ex)
    {
        Logger.LogError(ex);
    }

    Thread.Current.Sleep(15*1000);
}

しかし、私は疑問に思い始めました-これを行うためのより良い方法はありますか? ここで Tasks ライブラリを使用する価値はありますか?..何か他のものはありますか?

それが重要な場合、私は.Net 4.0を使用しています。

ありがとうございました。

4

4 に答える 4

1

タイマーを使用します。10分ごとに(または何でも)設定して、アップロードを行います。

System.Threading.Timer uploadTimer = new Timer(UploadProc, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));

void UploadProc(object state)
{
    // do query, upload, and update logic here
}

ほとんどの時間をスリープに費やす明示的なスレッドは必要ありません。

もっと頻繁にしたい場合 (この例では 15 秒あります)、リエントラント タイマー ティックが発生する可能性があります。つまり、15 秒に設定し、処理に 15 秒以上かかる場合、複数のスレッドが同時にアップロード コードを実行することになります。

その可能性がある場合は、2 つの選択肢があります。ロックを使用して再入を防止するか、プロセスごとに更新するワンショット タイマーを使用します。

ロックはかなり簡単です。クラス スコープでロック オブジェクトを定義します。

private object uploadLock = new object();

そして、UploadProc 内:

void UploadProc(object state)
{
    if (!Monitor.TryEnter(uploadLock))
    {
        // upload in progress. Quit.
        return;
    }
    try
    {
        // processing here
    } 
    finally
    {
        Monitor.Exit(uploadLock);
    }
}

それはうまくいきます。ワンショットのアイデアには、タイマーを 1 回ティックしてから停止するように設定することが含まれます。処理が完了したら、次のように更新します。

System.Threading.Timer uploadTimer = new Timer(
    UploadProc, null, TimeSpan.FromSeconds(15), TimeSpan.FromMilliseconds(-1));

void UploadProc(object state)
{
    // processing here
    // now reset the timer
    uploadTimer.Change(TimeSpan.FromSeconds(15), TimeSpan.FromMilliseconds(-1));
}
于 2013-03-29T18:59:02.993 に答える
0

これは基本的なプッシュとプルの問題です。データソースが通知できる場合は、それを行うことができますが、それ以外の場合は、あなたのアプローチが正しいと思います。これらのデータを取得する別のサービスを設定できます。

于 2013-03-29T18:59:48.523 に答える
0

DispatcherTimerこれにはクラスを使用しました。

使用例:

DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromSeconds(1);
dt.Tick += delegate(object s, EventArgs args) {

//Your Logic here!!    

};
timer.Start();

また、クラスは次のとおりです: DispatcherTimer

于 2013-03-29T19:19:50.750 に答える
0

Quartz を使用してジョブを定期的に設定します。Timer を使用することは、それを行うための最良の方法ではありませんが、それを行うための簡単な方法です。

http://quartznet.sourceforge.net/

また、ジョブにキューを使用することもできます。

于 2013-03-29T19:02:19.483 に答える