首页 文章

Invoke()和BeginInvoke()之间有什么区别

提问于
浏览
357

只是想知道 BeginInvoke()Invoke() 之间的区别是什么?

主要是每个人将用于什么 .

编辑:创建一个线程对象和调用它的调用之间的区别是什么,只是在委托上调用 BeginInvoke() ?或者它们是一样的吗?

6 回答

  • 6

    只是给出一个简短的,有效的例子来看看它们之间差异的影响

    new Thread(foo).Start();
    
    private void foo()
    {
      this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
        (ThreadStart)delegate()
        {
            myTextBox.Text = "bing";
            Thread.Sleep(TimeSpan.FromSeconds(3));
        });
      MessageBox.Show("done");
    }
    

    如果使用 BeginInvoke ,则MessageBox会同时弹出文本更新 . 如果使用 Invoke ,MessageBox会在3秒睡眠后弹出 . 因此,显示异步( BeginInvoke )和同步( Invoke )调用的效果 .

  • 8

    只需添加使用Invoke()的原因和时间 .

    Invoke()和BeginInvoke()都将您指定的代码封送到调度程序线程 .

    但与BeginInvoke()不同,Invoke()会停止您的线程,直到调度程序执行您的代码 . You might want to use Invoke() if you need to pause an asynchronous operation until the user has supplied some sort of feedback.

    例如,您可以调用Invoke()来运行显示“确定/取消”对话框的代码片段 . 在用户单击按钮并且您的编组代码完成后,将返回invoke()方法,您可以根据用户的响应进行操作 .

    请参阅C#第31章中的Pro WPF

  • 41

    Control.Invoke()Control.BeginInvoke() 之间的区别是,

    • BeginInvoke() 将在GUI线程上安排异步操作 . 安排异步操作后,代码将继续 . 一段时间后(您不确切知道何时)将执行您的异步操作

    • Invoke() 将执行您的异步操作(在GUI线程上)并等待您的操作完成 .

    一个合乎逻辑的结论是,传递给 Invoke() 的委托可以有out参数或返回值,而传递给 BeginInvoke() 的委托则不能(你必须使用EndInvoke来检索结果) .

  • 516

    你的意思是Delegate.Invoke / BeginInvoke还是Control.Invoke / BeginInvoke?

    • Delegate.Invoke:在同一个线程上同步执行 .

    • Delegate.BeginInvoke:在线程池线程上异步执行 .

    • Control.Invoke:在UI线程上执行,但调用线程在继续之前等待完成 .

    • Control.BeginInvoke:在UI线程上执行,并且调用线程不等待完成 .

    蒂姆的回答提到你可能想要使用BeginInvoke - 尽管它主要面向Delegate.BeginInvoke,我怀疑 .

    对于Windows窗体应用程序,我建议您通常应该使用BeginInvoke . 这样你就不会修改UI线程可能用于显示目的的数据 . 例如,如果您有一个具有FirstName和LastName属性的Person,那么您执行了以下操作:

    person.FirstName = "Kevin"; // person is a shared reference
    person.LastName = "Spacey";
    control.BeginInvoke(UpdateName);
    person.FirstName = "Keyser";
    person.LastName = "Soze";
    

    然后UI可能最终显示“Keyser Spacey” . (外面的机会可以显示“Kevin Soze”,但只能通过记忆模型的怪异 . )

    但是,除非你遇到这种问题,否则Control.BeginInvoke更容易正确,并且会避免你的后台线程无需等待 . 请注意,Windows窗体团队已经保证您可以以“即发即忘”的方式使用Control.BeginInvoke - 即无需调用EndInvoke . 对于异步调用一般情况并非如此:通常每个BeginXXX都应该有相应的EndXXX调用,通常在回调中 .

  • 14

    在Jon Skeet的回复基础上,有时您想要调用委托并等待其执行在当前线程继续之前完成 . 在这些情况下,Invoke调用就是你想要的 .

    在多线程应用程序中,您可能不希望线程等待委托完成执行,特别是如果该委托执行I / O(可能使委托和您的线程阻塞) .

    在这些情况下,BeginInvoke会很有用 . 通过调用它,您告诉委托开始,然后您的线程可以自由地与委托并行执行其他操作 .

    使用BeginInvoke会增加代码的复杂性,但有时候改进的性能值得复杂 .

  • 22

    Delegate.BeginInvoke()以异步方式对委托的调用进行排队,并立即返回控制 . 使用Delegate.BeginInvoke()时,应该在回调方法中调用Delegate.EndInvoke()来获取结果 .

    Delegate.Invoke()在同一个线程中同步调用委托 .

    MSDN Article

相关问题