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番目のアプローチはハングしないことに気づきました。
助けてください
BeginInvoke
は、Form
と同じスレッドで、メッセージポンプのメッセージキューにアクションを投稿します。新しいスレッドは作成されません。
Control.BeginInvoke
は非同期スレッド開始と同様に動作しますが、重要な内部の違いがあります。
記事をさらに詳しく読む ここ 。
BeginInvokesは、ウィンドウにメッセージを投稿することにより、UIスレッドで非同期的にデリゲートを実行します(これがUIをハングさせる理由です)。デリゲートのコードがUIにアクセスする場合は、これを行う必要があります。
Thread.Startを使用したアプローチでは、新しい独立したスレッドでデリゲートが実行されます。
これを試して。
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フラグを試して、ロックしてください。
私が質問に答えたことを願っています。
レオ・ブルザニティ
Thread.Start
新しいThread
で実行します。
Control.BeginInvoke
これが属するコントロールのスレッドで、メソッドを実行します。現在コントロールのスレッドを使用している場合、コントロールをメッセージループに戻すまで、メソッドは実行されません。イベントハンドラを終了します。
他の人が投稿したように、Thread.Startは新しいスレッドを起動し、Control.BeginInvoke()はUIスレッドでコードを実行します(たとえば、フィールドの値を変更する場合に必要です)。
ただし、WinFormsでバックグラウンドタスクを実行するための最も簡単な手法は、 BackgroundWorker を使用することです。それをフォームにドロップし、イベントを接続して、RunWorkerAsync()を呼び出します。次に、DoWorkイベントでバックグラウンドタスクを記述します。 UIの更新は、RunWorkerCompletedイベントに入れることができます。
BackgroundWorkerを使用すると、煩わしいスレッド処理やIsInvokeRequiredをすべて回避できます。
これがより詳細な ハウツー記事 です。
違いは、BeginInvokeメソッドが同じスレッドで非同期にデリゲートを呼び出すだけであるということです。
Thread.Startを使用すると、まったく異なるスレッドを作成できます。
Thread.Startは、間違いなくパフォーマンスを向上させます。