18

ご挨拶、私はC#でいくつかのアプリケーションを開発しています。現在、私は糸脱毛を扱っていますが、頭に浮かぶ質問があります。InvokeとBeginInvokeの違いは何ですか?私はいくつかのスレッドを読みました、そして私はここでいくつかの有用な情報を見つけました:ここに

ただし、次のコードのInvokeとBeginInvokeの違いは何ですか。

private void ProcessRoutine()
{
   for (int nValue = StartFrom; nValue <= EndTo; nValue++)
   {
      this.Invoke(this.MyDelegate, nValue);
      //this.BeginInvoke(this.MyDelegate, nValue);
   }
   MessageBox.Show("Counting complete!");
}
private void MessageHandler(int progress)
{
    lblStatus.Text = lblStatus.Text = "Processing item: " + progress.ToString();
    progressBar1.Value = progress;
}

ここで、MyDelegateはMessageHandler関数への参照です。

BeginInvoke lblStatus.Textを使用しても、Invokeを使用するとラベルが更新されるのに対し、Textは更新されないことに気付きました。さらに、Invokeは実行が完了するのを待つことを知っています。私が興味を持っている最も重要なケースは、この場合、ラベルテキストの更新に違いがある理由です。

4

5 に答える 5

19

まず、リンクから:

  • Control.Invoke:UIスレッドで実行されますが、呼び出し元のスレッドは完了を待ってから続行します。
  • Control.BeginInvoke:非同期UIスレッドで実行され、呼び出し元のスレッドは完了を待ちません。

およびMSDNから:

BeginInvokeは、コントロールの基になるハンドルが作成されたスレッドで、指定されたデリゲートを非同期的に実行します。

要約すると、BeginInvoke非同期です。UIスレッドからが呼び出されるとBeginInvoke、リクエストはUIスレッドと並行して実行されます。つまり、現在実行中のメソッドが戻るまで実行されない可能性があります。したがって、この場合、呼び出し元のスレッドは続行する前にこのイベントが完了するのを待たないため、forループが中断されないため、テキストボックスが更新されているようには見えません。

または、同期Invokeです。呼び出し元のスレッドは呼び出しが完了するのを待ってから実行を続行するため、テキストボックスが更新されます。

于 2009-12-15T19:44:15.267 に答える
8

Invokeを使用すると、メソッドが実行され、アプリケーションはメソッドが完了するのを待ちます。

BeginInvokeを使用すると、メソッドは非同期で呼び出され、BeginInvokeで参照されているメソッドが実行されている間、アプリケーションは実行を継続します。

BeginInvokeでは、EndInvokeを呼び出して、BeginIvnokeを使用して実行したメソッドの結果を取得する必要があります。

Invokeメソッドとは異なり、GUIスレッドとは別のスレッドで実行されるため、BeginXXXメソッドのGUIコンポーネントを更新しないでください。GUIスレッドとは別のスレッドのGUIコンポーネントにアクセスすることはできません。

お役に立てれば!

于 2009-12-15T19:44:12.133 に答える
6

Control.BeginInvoke別のスレッド(またはスレッドプール)では機能しません。delegate.BeginInvokeは機能します。MSDNのワンライナーは次のように述べています。

コントロールの基になるハンドルが作成されたスレッドで、指定されたデリゲートを非同期で実行します。

ただしControl.BeginInvoke、単にPostMessageを使用して戻り、CLRThreadは作成されません。

PostMessage関数は、指定されたウィンドウを作成したスレッドに関連付けられたメッセージキューにメッセージを配置(投稿)し、スレッドがメッセージを処理するのを待たずに戻ります。

この記事でInvokeは、使用するかどうかをまとめBeginInvokeています。

どの関数を使用するかを尋ねます。それは本当にあなたの要件に依存します。続行する前にUIの更新を完了させたい場合は、Invokeを使用します。そのような要件がない場合は、BeginInvokeを使用することをお勧めします。これにより、スレッドがそれを「より速く」呼び出すように見えます。ただし、BeginInvokeにはいくつかの落とし穴があります。

  • BeginInvokeを介して呼び出している関数が共有状態(UIスレッドと他のスレッド間で共有されている状態)にアクセスする場合は、問題が発生しています。BeginInvokeを呼び出してから、ラップされた関数が実際に実行されるまでの間に状態が変化し、タイミングの問題を見つけるのが困難になる可能性があります。
  • BeginInvokeを介して呼び出された関数に参照パラメーターを渡す場合は、関数が完了する前に、渡されたオブジェクトを他の人が変更しないようにする必要があります。通常、BeginInvokeに渡す前にオブジェクトのクローンを作成します。これにより、問題が完全に回避されます。
于 2010-02-10T12:53:20.993 に答える
1

BeginInvokeは、別のスレッドでメソッド本体を実行し、現在のスレッドを続行できるようにします。別のスレッドからコントロールプロパティを直接更新しようとすると、例外がスローされます。

于 2009-12-15T19:42:53.337 に答える
0

これは基本的に、コントロールを同期的または非同期的に更新するかどうかに要約されます。これはすべてあなたの特定の状況に依存します。

于 2009-12-15T19:43:50.637 に答える