2016-03-02 60 views
2

我正在尝试开发Windows应用程序并遇到问题。 我有一个MainPage.xaml和另外两个StartScreen.xaml和Player.xaml。 如果某些条件为真,我将切换MainPage的内容。 因此,我在StartScreen中有一个事件,它检查一个目录是否存在,但每次发生错误时都会抛出。在UI线程上执行同步操作

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 = ""; 
     } 

    } 

当它击中else分支一切都很好,但是当DIR可我收到以下错误信息:

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

其他信息:同步操作不应该在UI线程上执行。考虑在Task.Run中封装这个方法。

即使我评论if分支中的代码,错误仍然存​​在。

我尝试这样做:

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 = ""; 
      } 
     }); 
    } 

仍是同样的错误,我的理解这应该是异步运行并等待代码完成,但它似乎并不如此。我也尝试了其他的东西,但仍然得到错误。 我不知道如何解决这个问题,有人可以解释为什么会发生这种情况,以及如何解决这个问题。

回答

2

正如例外所述,您不允许在UI线程中同步调用Directory.Exists。将整个代码块放入Dispatcher动作仍然在UI线程中调用它。

在UWP应用程序,你通常会使用StorageFolder.TryGetItemAsync方法来检查,如果一个文件或文件夹是否存在:

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) 
    { 
     ... 
    } 
} 

注意,你仍然可以得到一个UnauthorizedAccessException当应用程序不允许访问main.workingDir

1

错误消息告诉你,你需要知道的一切:

考虑Task.Run

包装这种方法

你应该在通话包裹代码Task.Run。这将确保它在后台线程上运行。万一有人

背景资料在乎:

我认为,根据您的示例代码,您正在阅读的音乐库。在这种情况下,.NET文件API会通过WinRT API下载,因为它是一个代理位置。由于底层的WinRT API是异步的,因此.NET必须做些工作才能给你带来同步行为的幻觉,并且他们不希望在UI线程上做到这一点。

如果您只处理自己的本地数据文件夹,则.NET API将使用底层的Win32 API(已同步),因此无需任何后台线程要求即可工作。