16

次の進捗状況を追跡する最良の方法は何ですか?

long total = Products.LongCount();
long current = 0;
double Progress = 0.0;

Parallel.ForEach(Products, product =>
{
    try
    {
        var price = GetPrice(SystemAccount, product);
        SavePrice(product,price);
    }
    finally
    {
        Interlocked.Decrement(ref this.current);
    }});

進捗変数を 0.0 から 1.0 (現在/合計) に更新したいのですが、並列処理に悪影響を与えるようなものは使用したくありません。

4

3 に答える 3

15

このような単純な同期が必要な場合は、Jon のソリューションが適切です。最初の試行では、ほとんどの場合、lock. しかし、ロックによって処理が非常に遅くなることを測定した場合は、 のようなものを使用することを検討する必要がありますInterlocked

この場合、現在のカウントをインクリメントし、プロパティInterlocked.Incrementに変更するために使用します。Progress

private long total;
private long current;
public double Progress
{
    get
    {
        if (total == 0)
            return 0;
        return (double)current / total;
    }
}

…

this.total = Products.LongCount();
this.current = 0;

Parallel.ForEach(Products, product =>
{
    try
    {
        var price = GetPrice(SystemAccount, product);
        SavePrice(product, price);
    }
    finally
    {
        Interlocked.Increment(ref this.current);
    }
});

また、例外をどうするかを検討することもできます。例外で終了した反復を完了としてカウントする必要があるかどうかはわかりません。

于 2013-01-26T13:01:03.767 に答える
4

いくつかの簡単な計算を行っているだけなので、適切なオブジェクトをロックして原子性を確保します。

long total = Products.LongCount();
long current = 0;
double Progress = 0.0;
var lockTarget = new object();

Parallel.ForEach(Products, product =>
{
    try
    {
        var price = GetPrice(SystemAccount, product);
        SavePrice(product,price);
    }
    finally
    {
        lock (lockTarget) {
            Progress = ++this.current / total;
        }
    }});
于 2013-01-26T12:05:59.450 に答える
2

本体でブロッキングを使用しないソリューション:

long total = Products.LongCount();
BlockingCollection<MyState> states = new BlockingCollection<MyState>();

Parallel.ForEach(Products, () =>
{
    MyState myState = new MyState();
    states.Add(myState);
    return myState;
},
(i, state, arg3, myState) =>
{
    try
    {
        var price = GetPrice(SystemAccount, product);
        SavePrice(product,price);
    }
    finally
    {
        myState.value++;
        return myState;
    }
},
i => { }
);

次に、現在の進行状況にアクセスするには:

(float)states.Sum(state => state.value) / total
于 2013-01-26T12:13:01.320 に答える