2013-06-11 58 views
1

我正在嘗試使用C#在Windows應用商店中製作epub解析應用,並且它不會等待存檔(epub實際上是zip文件)來完成在嘗試解析尚未存在的目錄之前進行解壓縮。如何讓我的應用程序更耐心?我嘗試使我的UnZip()函數返回一個任務,並讓epub構造函數(epub是一個類)使用UnZip()。等待(),但這只是凍結了應用程序。我該怎麼辦?製作C#Windows應用商店應用等待解壓縮完成

編輯:這是我的相關代碼:

public class epub 
{ 
    public string filename; 
    private StorageFolder unzipFolder; 
    private IList<epubChapter> _contents; 
    private bool _parsed = false; 
    public bool parsed { get { return _parsed; } } //Epub and contents are fully parsed 

    public epub(string newFilename) 
    { 
     _contents = new List<epubChapter>(); 
     filename = newFilename; 
     UnZipFile().Wait(); 
     getTableOfContents(); 
    } 

    private async Task UnZipFile() 
    { 
     var sourceFolder = Windows.ApplicationModel.Package.Current.InstalledLocation; 
     StorageFolder localFolder = ApplicationData.Current.LocalFolder; 

     unzipFolder = await localFolder.CreateFolderAsync(filename, CreationCollisionOption.OpenIfExists); 

     using (var zipStream = await sourceFolder.OpenStreamForReadAsync(filename)) 
     { 
      using (MemoryStream zipMemoryStream = new MemoryStream((int)zipStream.Length)) 
      { 
       await zipStream.CopyToAsync(zipMemoryStream); 

       using (var archive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Read)) 
       { 
        foreach (ZipArchiveEntry entry in archive.Entries) 
        { 
         if (entry.Name != "") 
         { 
          using (Stream fileData = entry.Open()) 
          { 
           try 
           { 
            await unzipFolder.GetFileAsync(entry.Name); 
            Debug.WriteLine("File at {0} already exists", entry.Name); 
            continue; 
           } 
           catch (FileNotFoundException) 
           { 
            Debug.WriteLine("Creating file {0}", entry.Name); 
           } 

           StorageFile outputFile = await unzipFolder.CreateFileAsync(entry.Name, CreationCollisionOption.OpenIfExists); 

           //Debug.WriteLine("Output file created at {0}", outputFile.Path); 
           using (Stream outputFileStream = await outputFile.OpenStreamForWriteAsync()) 
           { 
            await fileData.CopyToAsync(outputFileStream); 
            await outputFileStream.FlushAsync(); 
           } 
          } 

          if (entry.Name == "toc.ncx") 
          { 
           Debug.WriteLine("toc.ncx found in epub file; parsing it"); 
           getTableOfContents(); 
          } 
         } 
        } 
       } 
      } 
     } 
    } 

    public void getTableOfContents() 
    { 
     string contentsPath = unzipFolder.Path + @"\toc.ncx"; //The file is always called this in valid epubs 

     try 
     { 
      XDocument toc = XDocument.Load(contentsPath); 
      string nameSpace = getNameSpace(toc); 
      XElement navMap = firstElementNamed(toc.Root, "navMap"); 
      parseNavPoints(navMap, nameSpace, 0); 
      _parsed = true; 
     } 
     catch(FileNotFoundException) 
     { 
      Debug.WriteLine("File toc.ncx was not found!"); 
     } 

    } 
+1

顯示代碼,如果沒有它,很難做到。 –

+0

如何在'UnZip'而不是'Wait'上使用'await'? – Romoku

+0

@Romoku:我試着在UnZip上使用await(並且將UnZip()的調用移動到一個新函數中,因爲構造函數不能是異步的),但是這並沒有幫助。 –

回答

2

基本上,你的問題似乎是:我如何從調用構造函數中async方法?

簡而言之,您不需要,而是爲您的班級創建一個async工廠方法。

較長的答案:正如你注意到的,if you call Wait(), your code will block。您不能使用await,因爲構造函數不能是async。如果你什麼都不做,構造函數會返回得太早。

這裏的解決方案是使用工廠方法而不是構造函數。例如:

private epub(string newFilename) 
{ 
    _contents = new List<epubChapter>(); 
    filename = newFilename; 
} 

public static async Task<epub> CreateAsync(string newFilename) 
{ 
    var result = new epub(newFilename); 
    await result.UnZipFile(); 
    result.getTableOfContents(); 
    return result; 
} 

有關更多信息和替代解決方案,請參閱Stephen Cleary's article about async and contructors

+0

謝謝,這樣做! –