0

次のようなものを含む[STAThread]メインがあります。

try
{
    // Start the port enumerator.

    Enumerator enumerator = new Enumerator();

    // Display the main window and start everything going.

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new TopViewForm(ref enumerator));
}
catch (Exception)
{
}

列挙子オブジェクト自体には、バックグラウンドワーカースレッドが含まれています。バックグラウンド作業は次のように初期化されます。

MyBackgroundWorker = new BackgroundWorker();
MyBackgroundWorker.WorkerSupportsCancellation = true;
MyBackgroundWorker.WorkerReportsProgress = true;
MyBackgroundWorker.DoWork +=new DoWorkEventHandler(MyBackgroundWorker_DoWork);
MyBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(MyBackgroundWorker_ProgressChanged);
MyBackgroundWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(MyBackgroundWorker_RunWorkerCompleted);
MyBackgroundWorker.RunWorkerAsync();

ここで、進行状況をメインフォーム(TopViewFormのインスタンス)に報告するために、列挙子のスレッドは適切なユーザーオブジェクトを使用してReportProgressを呼び出しています。ReportProgressは、ProgressChangedイベントの形式で到着し、メインUIスレッドで実行されます。これは、列挙子自体が作成されたスレッドです(つまり、BackgroundWorkerのスレッドではありません)。

この場合、このオブジェクトからのイベントに応答してメインプロセススレッドのTreeViewにノードを設定しようとすると、クロススレッド違反エラーが発生する可能性はありますか?ProgressChangedは、呼び出しスタックを見ると、メインプロセススレッドで実行されているようには見えません。

それでは、Application.Runが新しいスレッドを生成し、それを使用してフォームを実行するとしますか?しかし、ドキュメントには別の言い方があります。ばかげた間違いをしたか、ここで理解できないことがあります。

誰か考えがありますか?

4

2 に答える 2

3

進行状況の変更イベントがApplication.Run最初に呼び出される前に実行されていると思います。バックグラウンド ワーカーを からMainではなく、いずれかのフォーム内から開始する場合、バックグラウンド ワーカーが作成されて進行状況の報告を開始するときに、メッセージ ループが既に存在していることを確認できます。

于 2012-05-03T14:45:19.923 に答える
2

BackgroundWorker は、機能するために設定されている現在の SynchronizationContext に依存しています。ProgressChanged イベントはSendOrPostCallback Delegateとして実装され、msdn ドキュメントに記載されているように、SendOrPostCallback は、メッセージが同期コンテキストにディスパッチされるときに実行するコールバック メソッドを表します。フォーム デザイナーで BackgroundWorker をフォームに追加すると、SynchronizationContext が適切に設定されます。あなたの場合、BackgroundWorker には SynchronizationContext が割り当てられていません。

于 2012-05-03T14:46:47.663 に答える