2016-10-15 10 views
1

私はユニバーサルアプリケーションを書くことを学ぼうとしています。私はWinFormsで書いた別のプロジェクトを再作成しようとしています。私は、任意のフォルダ内のログファイルから読み取ることができる必要があり、私はそれを理解するように、フォルダにアクセスするためのユーザーのアクセス許可を取得する必要があります。私はアクセストークンを保存して、今後そのフォルダを再読み込みする必要があります。私は周りを読んで、次のコードを一緒に書きました:Universalアプリで任意のフォルダを読み込む方法は?

Friend Async Function GetLogFolder() As Task(Of StorageFolder) 
    Dim myLogFolder As StorageFolder 
    If ApplicationData.Current.LocalSettings.Values.ContainsKey("LogFolder") Then 
     Dim sToken As String = ApplicationData.Current.LocalSettings.Values("LogFolder") 
     myLogFolder = StorageApplicationPermissions.FutureAccessList.GetFileAsync(sToken) 
    Else 
     Dim myFolderPicker As FolderPicker = New FolderPicker 
     myFolderPicker.FileTypeFilter.Add("*") 
     myLogFolder = Await myFolderPicker.PickSingleFolderAsync 

     Dim sToken As String = StorageApplicationPermissions.FutureAccessList.Add(myLogFolder) 
     ApplicationData.Current.LocalSettings.Values.Add("LogFolder", sToken) 
    End If 
    Return myLogFolder 
End Function 

しかし、それは動作していないようです。この段階では、TextBlockとButtonだけを含むフォームがあります。ボタンをクリックすると、指定されたフォルダ内のすべての* .logファイルを解析するメソッドが呼び出されます。私はすべてのフリーズ、フォルダブラウザのようなダイアログが、を取得し、私は、Visual Studioとヒットストップに切り替えて、コードが実行されると

Dim myFolder As StorageFolder = GetLogFolder.Result 

、と私はボタンをクリックします。それが最初に行うことです。私はおそらく、ばかげたエラーを作りましたが、それが何であるか把握できません。

ご協力いただければ幸いです。

答えて

1

この問題は、ファイルアクセスコードそのものに起因するものではなく、非同期APIの使用方法によるものです。

GetLogFolderメソッドがTaskStorageFolderを返すため、Resultプロパティを使用する代わりに、結果を待つ必要があります。その理由は、async/awaitパターンでは、別のスレッドでI/O作業を行うことができますが、終了時にUIスレッドに制御を戻します。。ここではGetLogFolderメソッドを呼び出して、FolderPickerを使用してユーザーがフォルダを選択できるようにします。 ここに問題があります - コントロールがコードに戻り、GetLogFolderメソッドによって返されたTaskResultプロパティを照会しているときに、ユーザーにフォルダピッカーが表示されます。 Resultプロパティを照会するとUIスレッドが停止し、Taskが終了して結果を得るまで待機します。残念ながら、ユーザーがフォルダを選択すると、コントロールはUIスレッドに戻り、残りのGetLogFolderメソッドの実行を続行し、デッドロックとなります。 ResultプロパティはUIスレッドがTaskの結果を待つのを停止し、TaskはUIスレッドが使用可能になるのを待ちます。どちらもアプリが完全にフリーズするように続行することはできません。

解決策は非常に簡単です - async/awaitキーワードを使用してください。 VB.NET here with a clear exampleで詳細を読むことができます。あなたのケースでは

最初のステップは、ボタンのClickハンドラメソッドasyncを作成し、次により内部のコードを置き換えるために、次のようになります。

Dim myFolder As StorageFolder = Await GetLogFolder 
関連する問題