c# - 在 UWP 应用程序中,如何重现异常,告知仅在非 UI 线程上允许同步 UI

标签 c# asynchronous uwp

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

根据我的理解,根据当前线程的类型,某些操作的行为应该有所不同。特别是,同步 I/O 方法应该引发 UI 线程上不允许同步 I/O 的异常。

例如,File.Exists、File.Move 或使用 FileStream 构造函数创建文件。我什至早些时候就遇到过这些异常,但现在不知道如何再次重现它们。他们都神秘地消失了。即使我将这些方法直接放在 Button.Click 处理程序中(在 UI 线程上执行,我相信 HasThreadAccess 为 true),它们仍然有效。

我相信这段代码在 2016 年 12 月我上次测试时一直抛出 InvalidOperationException:

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

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

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

最佳答案

明白了。由于某些奇怪的原因,System.IO 命名空间的同步方法对于不同位置的磁盘文件夹表现不同(在线程方面)。

这有效:

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

以下崩溃并显示“System.InvalidOperationException”和消息“不应在 UI 线程上执行同步操作”。考虑将此方法包装在 Task.Run':

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

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

即似乎禁止在 UI 线程上运行同步操作并不涉及允许此 I/O 的文件夹(至少是 ApplicationData.Current.LocalFolder),并且确实涉及不允许此 I/O 的文件夹。也许 UWP 的 .NET 代码中存在引发错误异常的错误?

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

编辑:

事实证明这是正确且符合预期的行为。在 UI 线程上时,WinRT 甚至不会尝试访问 LocalFolder 外部的资源,因为这会导致内部死锁(这就是 WinRT 在幕后工作的方式)。对于 LocalFolder 访问,允许使用 UI 线程进行同步 I/O。这就是为什么只有在访问 LocalFolder 外部的资源时,我才会在 UI 线程上收到 InvalidOperationException(而不是 UnauthorizedAccessException)。

UI 线程的问题在于像文件选择器这样的对象,它可以返回 LocalFolder(代理文件)之外的位置。在工作线程上访问此类文件不会抛出 UnauthorizedAccessException 并且会正常进行,但在 UI 线程上我们会得到 InvalidOperationException,因为该文件位于 LocalFolder 之外。因此,只能从工作线程访问代理文件(通过 native 异步方法或通过专用工作线程上的同步方法)。

关于c# - 在 UWP 应用程序中,如何重现异常,告知仅在非 UI 线程上允许同步 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41809930/

相关文章:

javascript - 等待异步函数的循环

ios - 在 Swift 中存储异步 Cloud Firestore 查询结果

c# - 在没有 ms-app 的情况下从 OAuth 重定向到 UWP 应用程序

ajax - Ionic 3 Cordova ajax 调用在 Windows 10 (UWP) 上失败

c# - 从具有嵌套母版页的内容页访问控件

c# - Xamarin Azure Active Directory 重定向 URI 错误

java - MappedByteBuffer 抛出 java.nio.BufferOverflowException

c# - 动态 Linq OR 与 int 和字符串

c# - .NET 3.5 DotNetZip 搜索提取文件时出现问题

uwp - 如何在 XamlCompositionBrushBase 中检索父视觉大小?