Bar*_*osz 8 c# console-application iprogress
我注意到以下行为.IProgress填充控制台输出消息时,它们会显示在错误的文件夹中.
var recounter = new IdRecounter(filePath, new Progress<string>(Console.WriteLine));
recounter.RecalculateIds();
Run Code Online (Sandbox Code Playgroud)
我正在努力提高我的封装,可重用性和设计技巧.所以,我有一个名为IdRecounter的类.我现在想在控制台应用程序中使用它,但稍后可能在WPF应用程序中使用它.
因此,我希望班级完全不知道它的环境 - 但同时我想报告"现场"行动的进展 - 因此,我使用IProgress类型,这将允许我将东西放入控制台,或者进入日志文件,或更新状态标签属性等.(如果不是这样的话,请告诉我)
因此,我注意到它倾向于以不正确的顺序将消息扔进控制台,例如处理文件1
处理文件4
处理文件5
处理文件3
全部完成!
处理文件2
当我切换IProgress(MyProgress.Report())时,Console.WriteLine()它按预期工作.
这是什么原因以及如何控制?
谢谢
Pet*_*iho 11
本Progress<T>类使用在其创建调用事件处理程序的线程当前同步上下文ProgressChanged事件.
在控制台应用程序中,默认同步上下文使用线程池来调用委托,而不是将它们封送回检索上下文的线程.这意味着每次更新进度时,都可以在不同的线程中调用事件处理程序(特别是如果进度更新快速连续发生).
由于线程的调度方式,无法保证线程池工作程序在另一个线程池工作程序在其他工作程序运行其任务之前实际运行其任务之前分配了任务.特别是对于相对简单的任务(例如发出进度消息),稍后排队的任务实际上是在先前排队的任务之前完成的.
如果您希望保证按顺序显示进度更新消息,则需要使用其他机制.例如,您可以设置生产者/消费者BlockingCollection<T>,其中您有一个线程消耗由报告进度的操作排队(生成)的消息.或者,当然,你可以直接打电话Console.WriteLine()(因为你已经验证过会工作).
请注意,这并不意味着您需要放弃使用的想法IProgress<T>.它只是意味着您需要提供自己的实现,而不是使用Progress<T>类,至少在控制台方案中.例如:
class ConsoleProgress : IProgress<string>
{
public void ReportProgress(string text)
{
Console.WriteLine(text);
}
}
Run Code Online (Sandbox Code Playgroud)
例如,这将允许您将IProgress<T>抽象保留在IdRecounter()类中,从而将该类型与UI上下文分离.它可以重用于控制台程序以及任何GUI API程序,例如Winforms,WPF,Winrt等.
底线:当您需要抽象GUI程序中所需的跨线程,同步上下文相关操作时,这Progress<T>是一个非常有用的实现IProgress<T>.它将在控制台程序中工作,但由于在这种情况下它将使用线程池,因此您可能无法获得确定性有序的输出,至少在没有包括与ProgressChanged事件处理程序的其他同步的情况下.
| 归档时间: |
|
| 查看次数: |
527 次 |
| 最近记录: |