2012-05-14 14 views
63

WinRT(Windows 8 Metro)のUIスレッドでコードを実行するにはどうすればよいですか?WinRTのUIスレッドでコードを実行

Invokeメソッドは存在しません。

+7

将来の読者への注意:アプリケーションに複数のウィンドウがある場合は、複数のUIスレッドとディスパッチャが存在することを覚えておいてください。 –

答えて

68

使用:あなたのUIスレッドから

は、実行:あなたのバックグラウンド(非UIスレッド)から

var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher; 

後の両方のCPに取り組むべきであり

dispatcher.RunAsync(DispatcherPriority.Normal, 
    <lambda for your code which should run on the UI thread>); 

を構築します。

+5

UI以外のスレッドでディスパッチャを取得する方法はありますか?現時点ではCoreWindow.GetForCurrentThread()からnullが返されます。 – Grigory

+3

いいえ。ディスパッチャはUIスレッドに関連付けられているため、UIスレッドでディスパッチャを取得する必要があります。ディスパッチャが取得されると、そのディスパッチャを覚えておくことができます。 XAMLアプリケーションを使用している場合、ほとんどのUIオブジェクトには使用できるディスパッチャメンバがあります。 –

+0

私のアプリのどの部分がUIスレッドで実際に動作していますか? FrameWorkView(Windows :: ApplicationModel :: Core :: IFrameworkView)を使用していて、Run()メソッドから取得したディスパッチャを使用できません。私はRunAsyncを介してMediaElementを作成しようとしているときにWrongThreadExceptionを取得しています。 – Habba

8

用途:

this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => Frame.Navigate(typeof(Welcome), this)); 

それは私のために動作します。

+3

これは実際にUIスレッドで実行することは実際には保証されません。これは、 "this"がUIコンテキスト内のオブジェクトである場合のみです。 – Luke

5

これは私の考えではるかに簡単な方法です。

UIに関連付けられたTaskSchedulerを取得します。

var UISyncContext = TaskScheduler.FromCurrentSynchronizationContext(); 

次に、新しいタスクを開始し、上記のUISyncContextで開始します。

Task.Factory.StartNew(() => { /* Do your UI stuff here; */}, new System.Threading.CancellationToken(), TaskCreationOptions.PreferFairness, UISyncContext); 
+0

FYI:InvalidOperationExceptionが発生しました。「現在のSynchronizationContextはTaskSchedulerとして使用できません。 – Akku

+0

InvalidOperationも取得します – LowDev1

+1

SynchronizationContextがnullです。だからあなたはその例外を受けているのです。私のコードに間違いはありません。 – Deeb

75

それは直接非UIスレッドからCoreWindowを取得する方が簡単です。 GetForCurrentThread()またはWindow.Currentnullを返す場合でも、次のコードはどこでも動作します。

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, 
    <lambda for your code which should run on the UI thread>); 

例えば:

using Windows.ApplicationModel.Core; 
+0

this.Iを使用しているときにUIスレッドからアクセスするとSystem.NotImplementedExceptionが発生します。 – Naren

+0

ここにこの例外はありませんでした。あなたのブロックの指示のように、他の場所から来ている可能性があります。 –

+0

Dispatcherにアクセスしようとしたときにこの例外が発生しました。ディスパッチャーを使用してコードを実行していません。 – Naren

0

DispatcherTimerもオプションです:

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, 
    () => 
    { 
     // Your UI update code goes here! 
    }); 

あなたはWindows.ApplicationModel.Core名前空間を参照する必要があります。

私は(...、CoreWindow.Dispatcher UWP-デザイナでは使用できません)XAML-デザイナーで実行されなければならないコードのためにそれを使用

var localTimer = new DispatcherTimer 
{ 
    Interval = TimeSpan.FromMilliseconds(0) 
}; 
localTimer.Tick += (timer, e) => 
{ 
    (timer as DispatcherTimer).Stop(); 
    action(); 
}; 
localTimer.Start(); 

免責事項:
私は、これがなければならないことに注意してください他のすべてが失敗した場合、最後の手段となります。

0

UWPでは、CaptureElementコントロールのSourceプロパティ(XAMLで定義されています)を設定しようとして問題が発生しました。別のスレッドで準備されているという不満がありました。 Page_Loadedイベントハンドラを介して呼び出されます。

previewControl.Dispatcher.TryRunAsync(CoreDispatcherPriority.Normal,() => { 
    previewControl.Source = _mediaCapture; 
}).GetAwaiter().GetResult(); 
関連する問題