2

Task次のように完了するとイベントを発生させる非同期実行があります。

task.ContinueWith(() => {
    if (MyEvent != null)
        MyEvent(this, EventArgs.Empty);
}

次に、イベントハンドラーはWPFコントロールのインスタンスを作成する必要があります。しかし、そうしようとすると、例外が発生しますThe calling thread must be STA, because many UI components require this。メソッドを呼び出すと、クラスコンストラクタで例外が発生しますInitializeComponent()

私の知る限り、通常、別々のスレッドからWPFコントロールにアクセスすることは、を使用して処理されDispatcher.Invoke、それは常に私のために機能したので、私はそれを試しました:

Dispatcher.Invoke(new Action(() =>
{
    InitializeComponent();
}));

しかし、その場合、例外が発生し続けます。別のスレッドからWPFコントロールのインスタンスを作成するにはどうすればよいですか?

または、完了イベントをメインUIスレッドにマーシャリングする方が良いアプローチかもしれません。はいの場合、どうすればそれを行うことができますか?

4

3 に答える 3

3

UIスレッドに関連付けられたDispatcherインスタンスを使用する必要があります。あなたがこのようなものを書いているなら:

Dispatcher.Invoke(new Action(() =>
{
    InitializeComponent();
}));

タスク本体では、呼び出し元のスレッドのディスパッチャーを使用しています。これは、プールのバックグラウンドスレッドである可能性があります。

とにかく、タスクでは、Dispatcherを直接使用しないでください。適切なタスクスケジューラを使用します。

var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.ContinueWhenAll(tasks.ToArray(),
    result =>
    {
        // Put you UI calls here

    }, CancellationToken.None, TaskContinuationOptions.None, ui);

ここtasksで、はデフォルトのスケジューラで実行されている一連のタスクです。

于 2012-05-25T05:36:51.743 に答える
1

私は過去にこれを行いました:

 Dispatcher.Invoke(DispatcherPriority.Normal,
                   new Action(
                        delegate()
                        {
                            // Access control created by main thread
                            textBlock.Text = msg;
                        }
                   ));
于 2012-05-25T05:30:25.983 に答える
1

別のスレッドのコンストラクターからInitializeComponentを呼び出すと、問題を探しているように見えます。オブジェクトはまだありません(コンストラクターにいます)

それをUIスレッドにマーシャリングして戻すと、通常はうまくいきますが、コンストラクターの実行中は、私には悪い考えのように見えます。

コントロールを非同期的に初期化する場合は、ロードされたイベントをサブスクライブするだけで、オブジェクトがそこにあることがわかります。計算/データ取得を行うスレッドを生成し、データをUIスレッドにマーシャリングして表示します。

于 2012-05-25T05:35:22.183 に答える