web-dev-qa-db-ja.com

BeginInvokeとThread.Startの違い

I/O操作の読み取り/書き込みを別のスレッドに委任するダイアログベースのアプリケーションがあります。

2つのアプローチの間に違いがあることを明確にしておきたいと思います。

最初のアプローチ:(私はこれをメインフォーム-Form.csで行っています)

delegate void Action();
Action _action = new Action(Method);
this.BeginInvoke(_action);

2番目のアプローチ:

Thread th = new  Thread( new ThreadStart(_action));
th.Start();

BeginInvokeがUIを1秒間ハングさせるのに対し、2番目のアプローチはハングしないことに気づきました。

助けてください

20
Ashish Ashu

BeginInvokeは、Formと同じスレッドで、メッセージポンプのメッセージキューにアクションを投稿します。新しいスレッドは作成されません。

Control.BeginInvokeは非同期スレッド開始と同様に動作しますが、重要な内部の違いがあります。

記事をさらに詳しく読む ここ

17
Kenan E. K.

BeginInvokesは、ウィンドウにメッセージを投稿することにより、UIスレッドで非同期的にデリゲートを実行します(これがUIをハングさせる理由です)。デリゲートのコードがUIにアクセスする場合は、これを行う必要があります。

Thread.Startを使用したアプローチでは、新しい独立したスレッドでデリゲートが実行されます。

8
Thomas Levesque

これを試して。

class Form1: Form
{
   public void ButtonWasClicked(object sender, EventArgs e)
   {
       /* Call the UI's Invoke() method */
       this.Invoke((MethodInvoker)delegate()
       {
           /* Stuff to do.. you can access UI elements too without
            * the nasty "Control accessed from another thread.."
            * Use BeginInvoke() only if you have code after this section
            * that you want the UI to execute without waiting for this 
            * inner blockto finish. 
            */
       });
   }
}

BeginInvoke()に関しては、メソッドが終了するのを待たずに、関数がすぐに戻り、次の行が実行されるなどのように使用されます。

違いは、スレッドを作成すると、他のスレッドと同じように、スレッドをより細かく制御できることです。 CrossThreadExceptionsが発生します!一方、IAsyncResultとBeginInvoke()を使用する場合、非同期操作はランタイムによって管理されるため、実行フローを制御することはできません。

呼び出しを使用すると、メソッドにさらにパラメーターを送信し、操作が終了したらメソッドを呼び出すこともできます。

MyDelegateWithTwoParam del = new MyDelegateWithTwoParam(_method);
AsyncCallback callback = new AsyncCallback(_callbackMethod);
IAsyncResult res = del.BeginInvoke(param1, param2, callback, null);

private void _callbackMethod(IAsyncResult iar) {
   /* In this method you can collect data that your operation might have returned.
    * If MyDelegateWithTwoParam has a return type, you can find out here what i was. */
}

私は両方をUI開発に広く使用しました。サービスのようなオブジェクトには、スレッドをもっと使用します。 (TCP接続)を維持してリッスンするオブジェクトと、バックグラウンドの非同期メソッドがUIの背後で機能することを考えてください(BackgroundWorkerも参照してください)。最初のアプローチが開始するのに余分な秒:Thread.Abort()も常に最善の解決策であるとは限りません。プロセスコードで_abortフラグを試して、ロックしてください。

私が質問に答えたことを願っています。

レオ・ブルザニティ

3
lb.

Thread.Start新しいThreadで実行します。

Control.BeginInvokeこれが属するコントロールのスレッドで、メソッドを実行します。現在コントロールのスレッドを使用している場合、コントロールをメッセージループに戻すまで、メソッドは実行されません。イベントハンドラを終了します。

3
Timbo

他の人が投稿したように、Thread.Startは新しいスレッドを起動し、Control.BeginInvoke()はUIスレッドでコードを実行します(たとえば、フィールドの値を変更する場合に必要です)。

ただし、WinFormsでバックグラウンドタスクを実行するための最も簡単な手法は、 BackgroundWorker を使用することです。それをフォームにドロップし、イベントを接続して、RunWorkerAsync()を呼び出します。次に、DoWorkイベントでバックグラウンドタスクを記述します。 UIの更新は、RunWorkerCompletedイベントに入れることができます。

BackgroundWorkerを使用すると、煩わしいスレッド処理やIsInvokeRequiredをすべて回避できます。

これがより詳細な ハウツー記事 です。

1
Don Kirkby

違いは、BeginInvokeメソッドが同じスレッドで非同期にデリゲートを呼び出すだけであるということです。

Thread.Startを使用すると、まったく異なるスレッドを作成できます。

Thread.Startは、間違いなくパフォーマンスを向上させます。

0
Sk93