当前位置: 首页 > 编程语言 > C#

使用IProgress.Report()上报进度时,控制台消息显示顺序错误分享

时间:2023-04-10 12:45:50 C#

使用IProgress.Report()上报进度时,控制台消息显示顺序错误注意到以下行为。当IProgress填充控制台输出消息时,它们出现在错误的文件夹中。varrecounter=newIdRecounter(filePath,newProgress(Console.WriteLine));recounter.RecalculateIds();我正在努力提高我的封装、可重用性和设计技能。所以,我有一个名为IdRecounter的类。我现在想在控制台应用程序中使用它,但以后可能会在WPF应用程序中使用它。所以,我希望这个类完全不知道它的环境——但同时我想报告“实时”动作的进度——所以我使用IProgress类型,它允许我将东西放入控制台,或写入日志文件,或更新状态标签属性等(如果不是这种情况,请告诉我)因此,我注意到它倾向于以错误的顺序将消息扔到控制台中,例如处理文件1处理文件4加工文件5加工文件3全部搞定!处理文件2当我使用Console.WriteLine()切换IProgress(MyProgress.Report())时,它按预期工作。是什么原因,如何控制?谢谢Progress类使用创建它的线程的当前同步上下文来调用其ProgressChanged事件的事件处理程序。在控制台应用程序中,默认同步上下文使用线程池来调用委托,而不是将它们编组回检索上下文的线程。这意味着每次更新进度时都可以在不同的线程中调用事件处理程序(尤其是当进度更新快速连续发生时)。由于线程的调度方式,无法保证线程池工作线程会在另一个线程池工作线程实际运行其任务之前分派任务,然后另一个线程池工作线程运行其任务。特别是对于相对简单的任务(例如发出进度消息),很容易出现排队较晚的任务实际上比较早排队的任务完成的情况。如果要保证进度更新消息按顺序显示,则需要使用另一种机制。例如,您可以使用BlockingCollection来设置生产者/消费者,其中您有一个线程使用报告进度的操作排队(生产)的消息。或者,当然,您可以直接调用Console.WriteLine()(因为您已经验证过它会起作用)。请注意,这并不意味着您需要放弃使用IProgress的想法。这只是意味着您需要提供自己的实现而不是使用Progress类,至少在控制台场景中是这样。例如:classConsoleProgress:IProgress{publicvoidReportProgress(stringtext){Console.WriteLine(text);例如,这将允许您将IProgress抽象保留在IdRecounter()类中,从而将IdRecounter()类型与UI上下文分离。它可以重用于控制台程序以及任何GUIAPI程序,例如Winforms、WPF、Winrt等。底线:当您需要抽象跨线程、同步上下文相关操作时,Progress是一个非常有用的IProgress实现需要在GUI程序中。它将在控制台程序中运行,但由于在这种情况下它将使用线程池,因此您可能不会获得确定性的有序输出,至少不包括与ProgressChanged事件处理程序的额外同步。此类模仿控制台应用程序进度的基本行为:publicclassConsoleProgress:IProgress{privateActionaction;publicConsoleProgress(Actionaction){this.action=action;}publicvoidReport(Tvalue){action(value);}}只有动作,但是像Progress这样的事件的实现也很简单。以上就是C#学习教程:使用IProgress.Report()上报进度时,控制台消息显示顺序不正确的所有内容分享,如果对大家有用需要进一步了解C#学习教程,希望大家多多关注—本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: