サーチ…


タスク内からのUI要素へのアクセス

すべてのUI要素が作成され、プログラムのメインスレッドに常駐します。他のスレッドからのこれらのアクセスは、.netフレームワークランタイムによって禁止されています。基本的には、すべてのUI要素がスレッドに敏感なリソースであり、マルチスレッド環境でリソースにアクセスするにはスレッドセーフである必要があるからです。このクロス・スレッド・オブジェクト・アクセスが許可されている場合、最初は一貫性が影響を受けます。

このシナリオを考えてみましょう。

私たちは仕事の中で計算をしています。タスクは、メインスレッド以外のスレッドで実行されます。計算が進む間に、プログレスバーを更新する必要があります。これをする:

//Prepare the action
Action taskAction = new Action( () => {   
    int progress = 0;
    Action invokeAction = new Action( () => { progressBar.Value = progress; });
    while (progress <= 100) {
        progress = CalculateSomething();
        progressBar.Dispatcher.Invoke( invokeAction );
    }
} );

//After .net 4.5
Task.Run( taskAction );

//Before .net 4.5
Task.Factory.StartNew( taskAction ,
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.Default);

各UI要素には、 DispatcherObject祖先( System.Windows.Threading名前空間内)からのDispatcherオブジェクトがあります。 Dispatcherは、指定されたデリゲートを、Dispatcherが関連付けられているスレッドの指定された優先順位で同期して実行します。実行は同期化されているので、呼び出し元タスクはその結果を待つ必要があります。これにより、ディスパッチャーの代理人の内部でもint progressを使用できるようになりました。

UI要素を非同期的に更新してから、 invokeAction定義の変更を更新することができます。

//Prepare the action
Action taskAction = new Action( () => {   
    int progress = 0;
    Action<int> invokeAction = new Action<int>( (i) => { progressBar.Value = i; } )
    while (progress <= 100) {
        progress = CalculateSomething();
        progressBar.Dispatcher.BeginInvoke( 
            invokeAction,
            progress );
    }
} );

//After .net 4.5
Task.Run( taskAction );

//Before .net 4.5
Task.Factory.StartNew( taskAction ,
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.Default);

今回は、 int progressをパックし、デリゲートのパラメータとして使用しました。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow