Come posso eseguire il codice sul thread dell'interfaccia utente in WinRT (Windows 8 Metro)?Esegui codice su thread UI in WinRT
Il metodo Invoke
non esiste.
Come posso eseguire il codice sul thread dell'interfaccia utente in WinRT (Windows 8 Metro)?Esegui codice su thread UI in WinRT
Il metodo Invoke
non esiste.
Usa:
Dal tuo thread dell'interfaccia utente, eseguire:
var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
Dal tuo background (filo non UI)
dispatcher.RunAsync(DispatcherPriority.Normal,
<lambda for your code which should run on the UI thread>);
che dovrebbe funzionare su entrambi i CP e poi costruisce.
C'è un modo per ottenere il dispatcher sul thread non UI? Attualmente ottengo null da CoreWindow.GetForCurrentThread() – Grigory
No. I Dispatcher sono legati a un thread dell'interfaccia utente, quindi è necessario recuperare il dispatcher sul thread dell'interfaccia utente.Una volta che il dispatcher è stato recuperato, puoi ricordarlo. Se si utilizza un'applicazione XAML, la maggior parte degli oggetti dell'interfaccia utente disporranno di un membro del dispatcher che è possibile utilizzare. –
Quindi quali parti della mia app sono effettivamente in esecuzione in UI Thread? Sto usando un FrameWorkView (Windows :: ApplicationModel :: Core :: IFrameworkView), e non posso usare il dispatcher che ho acquisito da Run() - metodo. Ricevo WrongThreadException quando sto cercando di creare MediaElement tramite RunAsync. – Habba
Usa:
this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => Frame.Navigate(typeof(Welcome), this));
Funziona per me.
Questo fa in realtà non garantisce di eseguirlo sul thread dell'interfaccia utente. Lo farà solo se "questo" è un oggetto nel contesto dell'interfaccia utente. – Luke
Questo è un modo molto più semplice a mio parere.
Ottieni TaskScheduler associato all'interfaccia utente.
var UISyncContext = TaskScheduler.FromCurrentSynchronizationContext();
Quindi avviare una nuova attività e su UISyncContext precedente.
Task.Factory.StartNew(() => { /* Do your UI stuff here; */}, new System.Threading.CancellationToken(), TaskCreationOptions.PreferFairness, UISyncContext);
Nota: Ricevo un InvalidOperationException "L'attuale SynchronizationContext non può essere utilizzato come TaskScheduler". – Akku
Ho anche un Invalidoperation – LowDev1
Your SynchronizationContext è null. Ecco perché stai ricevendo quell'eccezione. Niente di sbagliato con il mio codice. – Deeb
E 'più facile per ottenere direttamente il CoreWindow dal thread non-UI. Il seguente codice funzionerà ovunque, anche quando GetForCurrentThread()
o Window.Current
restituisce null.
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
<lambda for your code which should run on the UI thread>);
ad esempio:
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
});
Avrai bisogno di fare riferimento Windows.ApplicationModel.Core
namespace:
using Windows.ApplicationModel.Core;
Ricevo System.NotImplementedException durante l'utilizzo. Accedo al thread dell'interfaccia utente. – Naren
Non ha mai avuto questa eccezione qui. Potrebbe provenire da qualche altra parte, come dentro le istruzioni del blocco. –
Ricevo questa eccezione quando ho provato ad accedere al Dispatcher. Non ho eseguito alcun codice utilizzando il dispatcher. – Naren
DispatcherTimer è anche un'opzione.
L'ho usato per il codice che deve essere eseguito in XAML-designer (CoreWindow.Dispatcher, ... non sono disponibili in UWP-designer)
var localTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(0)
};
localTimer.Tick += (timer, e) =>
{
(timer as DispatcherTimer).Stop();
action();
};
localTimer.Start();
Disclaimer:
Vorrei sottolineare che questo dovrebbe essere un'opzione di ultima istanza se tutti gli altri falliscono.
Su UWP, stavo avendo problemi nel tentativo di impostare la proprietà Source del controllo CaptureElement (che è definito in XAML), si lamentava di essere preparato su thread diversi, anche se stavo provando a impostarlo dal codice che era invocato tramite un gestore di eventi Page_Loaded. Ho finito per usarlo per aggirare il problema:
previewControl.Dispatcher.TryRunAsync(CoreDispatcherPriority.Normal,() => {
previewControl.Source = _mediaCapture;
}).GetAwaiter().GetResult();
Nota per i futuri lettori: Ricorda che se la tua app ha più finestre, ci sono più thread dell'interfaccia utente e dispatcher. –