在UWP应用程序中,如何重现异常,该异常告诉您仅在非UI线程上允许同步UI [英] In UWP application, how to reproduce exception telling that synchronous UI is allowed on non-UI threads only

查看:54
本文介绍了在UWP应用程序中,如何重现异常,该异常告诉您仅在非UI线程上允许同步UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法弄清楚不同类型的线程在UWP应用程序中的行为.首先,在UWP中,似乎UI线程不是主线程,它是辅助线程之一(在事件处理程序中插入断点等时,我在调试器中看到了这一点).我的假设是 CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess 指定当前线程是否为UI线程.

I can't figure out how threads of different types behave in UWP applications. First, in UWP it seems that UI thread is not a main thread, it's one of worker threads (I see this in the debugger when inserting breakpoints in event handlers and so on). My assumption is that CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess designates if the current thread a UI thread or not.

据我了解,某些操作应根据当前线程的类型而有所不同.特别是,同步I/O方法应引发一个例外,即UI线程上不允许同步I/O.

From my understanding some actions should behave differently depending on the type of the current thread. In particular, synchronous I/O methods should raise an exception that synchronous I/O is not allowed on UI thread.

例如,File.Exists,File.Move或使用FileStream构造函数创建文件.我什至实际上早些时候就得到了这些异常,但是现在不知道如何再次再现它们.他们都神秘地消失了.即使我将这些方法直接放在按钮中.单击处理程序(我相信它在UI线程上执行, HasThreadAccess 是正确的),它们仍然有效.

For instance, File.Exists, File.Move or creating a file with FileStream constructor. I even actually got these exceptions earlier but now can't figure out how to reproduce them again. They all are mysteriously gone. Even if I put these methods directly in a button.Click handler (which executes on UI thread, I believe, HasThreadAccess is true), they still work.

我相信当我上次测试它时,该代码在2016年12月不断抛出InvalidOperationException:

I believe this code kept throwing InvalidOperationException back in 2016 Dec when I tested it last time:

private async void button_Click(object sender, RoutedEventArgs e)
{
    if (File.Exists(Path.Combine(ApplicationData.Current.LocalFolder.Path, "log.txt")))
    {
    }

或者,也许代码很接近但不等于那个,也许我错过了一些重要的细节.

Or, maybe, the code was close but not equal to that, maybe I'm missing some important detail..

我需要找到一种方法使这些异常可靠地再次发生,以便我可以正确地重构旧的同步库以进行异步并进行彻底的测试.没有抛出异常,我实际上无法确定在其他人的系统上,该库不会由于这些I/O线程问题而崩溃.

I need to find a way to make these exceptions reliably occur again so that I could correctly refactor the old synchronous library to async and test it thoroughly. Without exceptions being thrown, I can't actually be sure that on someone's else system this library won't crash due to these I/O threading issues.

推荐答案

知道了.由于某些奇怪的原因,System.IO命名空间的同步方法对于不同位置的磁盘文件夹的行为(在线程方面)是不同的.

Got it. For some weird reason, synchronous methods of System.IO namespace behave differently (in terms of threading) for disk folders in different locations.

这有效:

FileStream fs = new FileStream(Path.Combine(ApplicationData.Current.LocalFolder.Path, "log.txt"), FileMode.OpenOrCreate);

以下内容因"System.InvalidOperationException"而崩溃,并且消息同步操作不应在UI线程上执行".考虑将这种方法包装在Task.Run'中:

The below crashes with 'System.InvalidOperationException' and message 'Synchronous operations should not be performed on the UI thread. Consider wrapping this method in Task.Run':

FileStream fs = new FileStream(@"C:\Temp\log.txt", FileMode.OpenOrCreate);

同时,如果我在工作线程而不是UI线程上运行后者,则会得到准确的UnauthorizedAccessException,告诉我Access被拒绝.

At the same time, if I run the latter on a worker thread rather than UI thread, I get accurate UnauthorizedAccessException telling me that Access is denied.

即似乎禁止在UI线程上运行同步操作与允许该I/O的文件夹(至少是ApplicationData.Current.LocalFolder)无关,而与无论如何都不允许该I/O的文件夹无关.也许是UWP的.NET代码中的错误引发了错误的异常?

I.e. it seems that prohibition to run synchronous operations on UI thread does NOT concern folders (at least ApplicationData.Current.LocalFolder) where this I/O is allowed and does concern folders where this I/O is not allowed anyway. Maybe a bug in .NET code for UWP that wrong exception is thrown?

这很奇怪,因为我认为线程和访问控制之间应该没有关系,但是至少我找到了一种使UWP同步方法崩溃的方法.

That's strange as I believe it should be no relation between threading and access control matters but at least I found a way to make UWP sync method crash in the way I needed.

结果证明这是正确的预期行为.在UI线程上时,WinRT甚至不会尝试访问LocalFolder之外的资源,因为这会导致内部死锁(这就是WinRT在后台运行的方式).对于LocalFolder访问,允许使用UI线程进行同步I/O.这就是为什么仅在访问LocalFolder之外的资源时,我才在UI线程上收到InvalidOperationException(而不是UnauthorizedAccessException).

Turns out it's the correct and expected behavior. When on UI thread, WinRT won't even try to access resources outside LocalFolder because it would cause internal deadlock (that's just how WinRT works under the hood). For LocalFolder access, using UI thread for sync I/O is allowed. That's why I'm getting InvalidOperationException (rather than UnauthorizedAccessException) on UI thread only when accessing resources outside LocalFolder.

UI线程出现问题的原因是文件选择器之类的对象,该对象可以返回LocalFolder(代理文件)之外的位置.在辅助线程上访问此类文件不会引发UnauthorizedAccessException,并且会很好,但是在UI线程上,我们将收到InvalidOperationException,因为该文件位于LocalFolder之外.因此,只能从工作线程访问代理文件(通过本地异步方法或专用工作线程上的同步方法).

The problem with UI thread will be with an object like file picker which can return location outside of LocalFolder (brokered file). Accessing such file on a worker thread won't throw UnauthorizedAccessException and will go just fine but on a UI thread we'll get InvalidOperationException because the file is outside LocalFolder. So, brokered files can only be accessed from a worker thread (either via natively async methods or via sync methods on a dedicated worker thread).

这篇关于在UWP应用程序中,如何重现异常,该异常告诉您仅在非UI线程上允许同步UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆