Perform synchronous operation on Ui thread

2019-02-25 11:47发布

I am trying develop a Windows App and run into issues. I have a MainPage.xaml and 2 others StartScreen.xaml and Player.xaml. I am switching content of the MainPage if certain conditions are true. So I have an event in StartScreen it checks if a directory exist or not but it throws me every time an error.

private void GoToPlayer_Click(object sender, RoutedEventArgs e)
    {

        if (Directory.Exists(this.main.workingDir + "/" + IDText.Text + "/Tracks")) // Error occurs here
        {
            this.main.Content = this.main.player; //here i switch between different ui forms
        }
        else
        {
            MessageBox.Text = "CD not found";
            IDText.Text = "";
        }

    }

When it hit the else branch everything is fine but when the dir is available I get the following error message:

An exception of type 'System.InvalidOperationException' occurred in System.IO.FileSystem.dll but was not handled in user code

Additional information: Synchronous operations should not be performed on the UI thread. Consider wrapping this method in Task.Run.

Even if I commenting the code in the if branch out the error still comes.

I tried this:

private async void GoToPlayer_Click(object sender, RoutedEventArgs e)
    {
        await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
            if (Directory.Exists(this.main.workingDir + "/" + IDText.Text + "/Tracks")) // Error occurs here
            {
                this.main.Content = this.main.player; //here i switch between different ui forms
            }
            else
            {
                MessageBox.Text = "CD not found";
                IDText.Text = "";
            }
        });
    }

Still the same error, as I understood this should be run asynchronous and wait until the code complete, but it doesn't seems so. I also tried bunch other stuff but still get the errors. I don't know how to fix that, could someone please explain why this is happening and how to fix that.

2条回答
你好瞎i
2楼-- · 2019-02-25 11:53

As the exception says, you are not allowed to call Directory.Exists synchronously in the UI thread. Putting the whole code block in a Dispatcher action still calls it in the UI thread.

In a UWP app you would usually use the StorageFolder.TryGetItemAsync method to check if a file or folder exists:

private async void GoToPlayer_Click(object sender, RoutedEventArgs e)
{
    var folder = await StorageFolder.GetFolderFromPathAsync(main.workingDir);

    if ((folder = await folder.TryGetItemAsync(IDText.Text) as StorageFolder) != null &&
        (folder = await folder.TryGetItemAsync("Tracks") as StorageFolder) != null)
    {
        ...
    }
}

Note that you may still get an UnauthorizedAccessException when the application is not allowed to access main.workingDir.

查看更多
看我几分像从前
3楼-- · 2019-02-25 11:58

[Update July 22 2018 with example]

The error message tells you everything you need to know:

Consider wrapping this method in Task.Run

You should wrap the code in a call to Task.Run. This will ensure it runs on a background thread.

Here is a simple example:

var picker = new FolderPicker();
picker.SuggestedStartLocation = PickerLocationId.MusicLibrary;
picker.FileTypeFilter.Add(".mp3");
var folder = await picker.PickSingleFolderAsync();
var result = await Task.Run(() => Directory.Exists(Path.Combine(folder.Path, "foobar")));
if (result)
{
  Debug.WriteLine("Yes");
}
else
{
  Debug.WriteLine("No");
}

Background information in case anyone cares:

I assume, based on your sample code, that you are reading the Music Library. In this case, the .NET file APIs go through the WinRT APIs under the covers since it is a brokered location. Since the underlying WinRT APIs are async, .NET has to do work to give you the illusion of synchronous behaviour, and they don't want to do that on the UI thread.

If you were only dealing with your own local data folders, the .NET APIs would use the underlying Win32 APIs (which are synchronous already) and so would work without any background thread requirements.

Note that on my machine, this appears to work even on the UI thread, so it might depend on the version of Windows that you are targeting.

查看更多
登录 后发表回答