0

次の非常に単純なシナリオがあります。一部のデータは、パーティション化できるDB(かなり大きなコレクション)に書き込む必要があります。しかし、私には2つの問題があります。

  1. 簡単な方法:プログレスバーを印刷するオプションが必要です。これにより、これまでに挿入されたレコードの数を知ることができます(スレッド間での共有カウンターのようなものです)。

  2. 難しいもの:各レコードにはタイムスタンプを付ける必要があります。タイムスタンプには開始時刻と間隔があります。残念ながら、タイムスタンプはレコードの一部ではありませんが、シーケンシャルプログラミングでは、現在のタイムスタンプを特定の間隔でインクリメントすることで簡単に計算できます。

これまでのところ、問題は、上記の制約を適切に実装する方法ですか?反復を促進するときに実行されているコードからループ本体を分離することはどういうわけか可能ですか(++iまたはnewTimeStamp = oldTimeStamp.AddSeconds(...)、並列化されるループ本体とは対照的に、その種のコードは常に単一のスレッドで実行されますか?可能であれば、コードスニペットは非常に役立ちますが、ポインタ/名前/キーワードさえも取得できます。ありがとうございます。

4

2 に答える 2

1

パート1では、ミューテックス(lockステートメント)を使用することも、Interlockedメソッドの1つだけを使用することもできます。

int counter = 0;
object counterLock = new object();
void IncreaseCounter()
{
    lock (counterLock)
        counter++;
}

int GetCounter()
{
    lock (counterLock)
        return counter;
}

また

int counter = 0;
void IncreaseCounter()
{
    Interlocked.Increment(ref counter);
}

int GetCounter()
{
    return Interlocked.Read(ref counter);
}

GUIから使用する場合は、カウンターの変更を適切なDependencyPropertyに伝達できます(WPFを使用している場合)。

2番目の部分では、レコードごとにタイムスタンプを個別に計算できないので、スレッド間で何も共有する必要がないのはなぜですか?あなたの質問をきちんと理解できなかったのかもしれませんが、問題2について詳しく教えてください。

于 2010-10-17T11:23:19.183 に答える
0

単一のスレッドでそれを行う必要はありません。一度に 1 つのスレッドだけがそれを行うようにする必要があります。

public class Synchoniser {

  private int _progress;
  private int _total;
  private int _counter;
  pricate object _sync;

  public Synchroniser(int total, int counterSeed) {
    _progress = 0;
    _total = total;
    _counter = counterSeed;
    _sync = new Object();
  }

  public void AdvanceProgress() {
    lock (_sync) {
      _progress++;
    }
  }

  public int GetProgress() {
    lock (_sync) {
      return 100 * _progress / _total;
    }
  }

  public int GetNextCounter() {
    lock (_sync) {
      _counter++;
      return _counter;
    }
  }

}

クラスのインスタンスを 1 つ作成し、それを各スレッドに渡します。これで、それぞれが進行を進め、次のカウンター値を取得できます。

于 2010-10-17T11:29:37.020 に答える