C#UWP该应用程序调用了一个为不同线程编组的接口

我有一个C#UWP应用程序,其中包含我想要每5秒调用一次的函数。 从按钮调用时该函数运行正常,并且Timer每隔5秒就调到调试控制台….当我从Timer调用该函数时,所有函数都会松动。 我明白了:

System.Exception未被用户代码处理HResult = -2147417842 Message =应用程序调用了为不同线程编组的接口。 (来自HRESULT的exception:0x8001010E(RPC_E_WRONG_THREAD))

我假设你的function触及应用程序的UI。 触摸UI的任何东西都需要在UI的调度程序线程上运行(大多数应用程序只有一个,直到你进入多个窗口应用程序)。

您可以使用Windows.UI.Xaml。 DispatcherTimer在调度程序线程上运行计时器。

如果需要在工作线程上运行代码,然后在调度程序线程上触摸UI,则可以调用Dispatcher。 RunAsync将调用编组回调度程序线程。

您通常可以通过Window.Dispatcher从Window中找到您的调度程序 。

var ignored = Window.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Do something on the dispatcher thread }); 

很可能你是从System.Threading使用Timer 。 该计时器的事件不会被视为常规GUI事件,如果您从该计时器调用的方法访问GUI项,则会导致问题,因为该线程不是GUI项的所有者。

使用System.Windows.FormsTimer 。 该计时器可以访问您的GUI项目。

实际上,您可以使用Reactive Extensions中的Observable.Interval,并明确指定要监视计时器事件的调度程序:

 Observable.Interval(TimeSpan.FromSeconds(1), Scheduler.Default) .ObserveOn(coreWindow.Dispatcher) .Subscribe(_ => Log.Warning("Dispatcher.HasThreadAccess: " + coreWindow.Dispatcher.HasThreadAccess)); 

我喜欢这种方法的是你明确说明在哪个线程上发生了什么(参见SubscribeOn和ObserveOn )。