jjzjj

c# - 为什么不控制更新/刷新中间过程

coder 2024-05-27 原文

我有一个带有 statusLabel 的 Windows 窗体 (C#.NET),我似乎无法在事件处理程序方法的进程中间进行更新。我的代码看起来像这样......

    void Process_Completed(object sender, EventArgs e)
    {

        string t = "Process is finished!";
        this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t });
    }

    void Process_Started(object sender, EventArgs e)
    {
        string t = "Process has begun";
        this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t });
    }

    private delegate void StatusLabelUpdator(string text);
    private void updateStatusLabel(string text)
    {
        StatusLabel1.Text = text;
        statusStrip1.Invalidate();
        statusStrip1.Refresh();
        statusStrip1.Update();
    }

当我运行代码时,一旦进程启动,就会触发 Process_Started 方法,几秒钟后会触发 Process_Completed 方法。出于某种原因,我无法让状态标签显示“进程已开始”。它只会显示“过程已完成!”。如您所见,我已尝试使包含状态标签的状态条无效、刷新和更新,但没有成功。我无法在状态标签本身上调用更新/刷新/无效,因为这些方法对它不可用。我做错了什么?

补充信息:

“流程”是通过单击表单上的按钮来启动的,该按钮会调用单独类中的方法,如下所示:

public void DoSomeProcess()
{
    TriggerProcessStarted();
    System.Threading.Thread.Sleep(2000);   // For testing..
    TriggerProcessComplete();
}

在 TriggerProcessxxxx 方法中,我使用此代码触发事件...

var EventListeners = EH.GetInvocationList();    //EH is the appropriate EventHandler
if (EventListeners != null)
{
    for (int index = 0; index < EventListeners.Count(); index++)
    {
        var methodToInvoke = (EventHandler)EventListeners[index];
        methodToInvoke.BeginInvoke(this, EventArgs.Empty, EndAsyncEvent, new object[] { });
    }
}

最后,我将 Application.DoEvents() 添加到 updateStatusLabel 方法中,但它没有帮助。我仍然得到相同的结果。这是我的更新方法。

private void updateStatusLabel(string text)
{
    StatusLabel1.Text = text;
    statusStrip1.Refresh();
    Application.DoEvents(); 
}

所以我猜“处理”发生在 UI 线程上,但事件处理程序是在它自己的线程上调用的,然后在 UI 线程上调用控件更新。这是一种愚蠢的做事方式吗?注意:包含 DoSomeProcess() 方法的类在我引用的单独的 .NET ClassLibrary 中。

最佳答案

如果您在 UI 线程上执行处理,则在处理运行时它将无法执行任何其他操作(例如重绘更新的标签)。因此,例如,如果处理是因为用户单击了一个按钮而发生的,并且由按钮单击处理程序触发(没有明确地将其放置在另一个线程上),则它在 UI 线程上运行。即使您更新了标签的文本,它也不会在收到绘制消息之前绘制,此时它可能正忙于处理。

答案是对 separate thread 进行长时间运行的处理.破解(恕我直言)是使用 Application.DoEvents让 UI 线程在处理过程中做一些 UI 的事情。如果您在更新标签之后和开始处理之前放置其中一个,标签将被重新绘制的可能性非常高。但是,在处理过程中,无法处理进一步的绘制事件(当有人将另一个应用程序窗口移到您的应用程序上并返回时,会导致窗口半画,等等)。因此我将其称为 hack(尽管,呃,嗯,我已经知道这样做了 :-))。

编辑 根据您的编辑进行更新:

回复

So I guess the "processing" is taking place on the UI thread but eventhandler is invoked on it's own thread...

我假设 DoSomeProcess 是从 UI 线程触发的(例如,直接响应按钮点击或类似事件)。如果是这样,那么是的,您的处理肯定是在 UI 线程上进行的。因为 TriggerProcessStarted 通过 BeginInvoke 触发你的回调异步,你不知道它什么时候会运行,但无论如何你的代码会立即启动处理,永不屈服,所以没有其他人能够捕获那个线程。由于这是 UI 线程,对委托(delegate)的调用将阻塞在设置标签文本的 Invoke 调用上,因此它必须等待 UI 线程(正忙于处理)。 (这是假设它安排在不同的线程上;无论哪种方式,我都无法 100% 说服自己,因为 Microsoft 有两个不同的 BeginInvoke——IIRC 的一位设计师承认这是一个 Really Dumb想法——自从我与这些东西抗争以来已经有一段时间了。)

如果您使 TriggerProcessStarted 同步调用您的回调,您应该没问题。但理想情况下,改为在其自己的线程上安排处理(如果它不执行 UI)。

关于c# - 为什么不控制更新/刷新中间过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2341731/

有关c# - 为什么不控制更新/刷新中间过程的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  4. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  5. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  6. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  7. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  8. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

    我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

  9. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  10. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

随机推荐