1

すべて、私は.NET4.5の下でasync/キーワードを使用して引き受ける高価なタスクを持っています。クラスawaitを介してバックグラウンドスレッドから進捗状況を報告します。Progress<T>

IProgress<T>タイプとして渡すオブジェクトProgressInfoは、実行中にこのタイプのオブジェクトを何度も作成および破棄するオーバーヘッドを回避するために、シングルトンクラスとして作成するオブジェクトです。クラスは

public class ProgressInfo : IDisposable
{
    public static ProgressInfo instance = null;
    public WorkbookProgressInfo workbookinfo { get; set; }
    public string progressMessage { get; set; }
    public int progressPercentage { get; set; }

    // Default constructor which has a few overloads 
    // for the class members above.
    protected ProgressInfo()
    {
    }
    ...

    // The default instance creator for the class. 
    // This also has overloads to allow changes to the 
    // class variables.
    public static ProgressInfo Instance()
    {
        if (instance == null)
            instance = new ProgressInfo();
        return instance;
    }
    ...
}

ReportProgressメソッドを介して進捗状況を報告しIProgress<ProgressInfo>

IProgress<CostEngine.ProgressInfo> progressIndicator =
    new Progress<CostEngine.ProgressInfo>(ReportProgress);

バックグラウンドスレッドからのレポートは、通常、グローバルProgressInfo progressInfoおよびグローバルIProgress<ProgressInfo> progressIndicatorのようなものを使用して行われます。

...
progressInfo = new ProgressInfo.Instance(workbookinfo, message, n);
progressIndicator.Report(progressInfo);
...

問題は、実行が小さく、実行時にオブジェクトが変更にProgressInfo渡されるのが速いため、テストすることです。ReportProgressReportProgress

if (progressInfo.workbookinfo != null)
{
    // Do stuff <- here progressInfo.workbookinfo is changing to null!
}

進捗状況を報告する費用を最小限に抑えながら、この問題を回避するにはどうすればよいですか?

御時間ありがとうございます。

4

1 に答える 1

4

ここで、アプリケーションの間違った部分を最適化しようとしています。

数千のオブジェクトは、アプリケーションにとって何の意味もありません。それらを作成しても、アプリケーションのパフォーマンスの問題にはならない可能性があります。ただし、問題になる可能性があるのはUIの更新です。これらの数千の進捗レポートが短期間で発生している場合は、UIを常に更新します。UIの更新には時間がかかるため、ボトルネックに遭遇した場合はここにあります。

ここでの正しいアプローチは、報告する必要があるものだけを報告することです。
たとえば、1分間に60.000回の反復が発生し、これらの反復のすべてを報告する場合、ミリ秒ごとにUIを更新しようとします。
プログレスバーに本当に1000FPSが必要ですか?疑わしい。
毎秒だけ報告するのは完全に良いでしょう。ただし、毎秒レポートを作成すると、独自のオーバーヘッドが発生します。

私がアプリケーションで行っているのは、パーセンテージが変更されたらすぐに報告することです。
これにより、実際の反復回数に関係なく、最大100のレポートが作成されます。
上記の例では、600回の反復ごとに報告します。

これを単純化するために、私は実際にと呼ばれるクラスを作成しましたProgressReporter
そのコンストラクターでは、ProgressInfoオブジェクトと反復の総数を作成するファクトリデリゲートを取ります。
これはReportProgress、現在の反復で渡すメソッドを提供します。
クラスは以前に報告されたパーセンテージを内部的に保存し、このメソッドを呼び出すと、新しいパーセンテージを計算します。異なる場合にのみ、ファクトリデリゲートを使用して新しいインスタンスを作成し、インスタンスProgressInfoを呼び出します。ReportIProgress<T>

ところで:バックグラウンド操作に数分ではなく数時間かかる場合は、これを変更して、パーセンテージが変更されたときではなく、パーセンテージの小数点以下第1位または第2位が変更されたときにレポートすることができます。
ここでのポイントは、ユーザーに数秒ごとにフィードバックを提供するレポートの量を見つけることです。

于 2013-02-08T11:35:33.773 に答える