In a UWP application, how to throw an exception indicating that the synchronous user interface is only allowed for threads other than the UI

I cannot understand how different types of flows behave in UWP applications. Firstly, in UWP it seems that the user interface thread is not the main thread, it is one of the workflows (I see this in the debugger when inserting breakpoints in event handlers, etc.). My assumption is that CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess indicates if the current thread is a UI thread or not.

From my understanding, some actions should behave differently depending on the type of current thread. In particular, synchronous I / O methods should lead to the exception that synchronous I / O is not allowed in the user interface thread.

For example, File.Exists, File.Move, or creating a file with the FileStream constructor. I even got these exceptions before, but now I can’t figure out how to reproduce them again. All of them mysteriously disappeared. Even if I put these methods directly on the button. The click handler (which runs in the user interface thread, I believe HasThreadAccess is true), they still work.

I believe that this code continued to throw InvalidOperationException back in 2016 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 this, maybe I miss an important detail.

I need to find a way to make these exceptions reliably repeated so that I can properly reorganize the old synchronous library for asynchronous testing and thoroughly test it. Without excluding the exception, I cannot be sure that on another system this library will not fail due to these problems with input / output streams.

+2
source share
1 answer

Got it. For some strange reason, the synchronous methods of the System.IO namespace behave differently (in terms of streaming) for disk folders in different places.

It works:

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

The message “System.InvalidOperationException” and the message “Synchronous operations should not be performed on the user interface thread are displayed below. Consider transferring this method to Task.Run ':

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

At the same time, if I run the latter in the workflow, and not in the user interface thread, I get an exact UnauthorizedAccessException telling me that Access is denied.

those. it seems that the prohibition of starting synchronous operations with the user interface stream does NOT apply to folders (at least ApplicationData.Current.LocalFolder), where this I / O is allowed and applies to folders where this I / O is not allowed in any case. Maybe the error in the .NET code for UWP was selected due to a wrong exception?

Strange, since I believe that this should not be any relationship between the streaming and access control processes, but at least I found a way to collapse the UWP synchronization method as I needed.

EDIT:

It has the correct and expected behavior. When WinRT does not even try to access resources outside LocalFolder in the user interface stream, because it will cause an internal deadlock (this is how WinRT works under the hood). For LocalFolder access, a user interface stream is allowed for I / O synchronization. This is why I get an InvalidOperationException (rather than an UnauthorizedAccessException) in the UI thread only when accessing resources outside of LocalFolder.

The problem with the UI thread will be with an object similar to a file collector that can return a location outside of LocalFolder (broker file). Access to such a file in the workflow will not lead to a failure of UnauthorizedAccessException and it will be fine, but in the user interface thread we will get an InvalidOperationException because this file is outside of LocalFolder. Thus, broker files can only be accessed from the workflow (either through asynchronous methods, or using synchronization methods in a dedicated workflow).

+2
source

Source: https://habr.com/ru/post/1015236/


All Articles