全部,我使用.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
传递给ReportProgress
的对象在ReportProgress
执行时发生了变化,所以我测试了
if (progressInfo.workbookinfo != null)
{
// Do stuff <- here progressInfo.workbookinfo is changing to null!
}
如何在保持报告进度最低费用的同时避免此问题?
感谢您的时间。
答案 0 :(得分:4)
您正在尝试优化应用程序的错误部分。
几千个对象对于应用程序来说都不算什么。最有可能创建它们不会是应用程序中的性能问题。但是,可能成为问题的是UI的更新。如果在短时间内发生了数千个进度报告,您将不断更新UI。更新UI会花费时间,所以如果你遇到瓶颈,它就会在这里。
这里的正确方法是仅报告您需要报告的内容 例如,如果您发生了60,000次迭代 - 比方说 - 一分钟并报告这些迭代中的每一次迭代,您将尝试每毫秒更新UI 。 你的进度条真的需要 1000 FPS 吗?我对此表示怀疑 每秒只报告一次是非常好的。但是,每秒报告会产生自己的开销。
我在申请时所做的是在百分比发生变化时立即报告 无论您实际拥有多少次迭代,这将导致最多100个报告 在上面的例子中,我将报告每600次迭代。
为了简化这一点,我实际创建了一个名为ProgressReporter
的类
在它的构造函数中,它需要一个工厂委托来创建ProgressInfo
对象和迭代总数
它提供了您在当前迭代中传递的ReportProgress
方法
该类在内部存储先前报告的百分比,并在调用此方法时计算新百分比。只有在不同的情况下,它才会使用工厂代理创建新的ProgressInfo
并在Report
实例上调用IProgress<T>
。
顺便说一句:如果您的后台操作不需要几分钟而是几小时,您可以将其更改为在百分比更改时报告,但在百分比的第一个或第二个小数更改时报告。 这里的要点是:查找一定数量的报告,每隔几秒就会给用户一次反馈。