2016-03-02 97 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(已同步),因此無需任何後臺線程要求即可工作。