制作一个C#Windows应用商店应用等待解压缩完成

时间:2013-06-11 14:38:19

标签: c# windows-8 zip async-await

我正在尝试使用C#在Windows应用商店中创建一个epub解析应用,它不会等待存档(epub实际上是zip文件)在尝试解析尚未存在的文件之前完成提取目录。如何使我的应用程序更耐心?

我试过让我的UnZip()函数返回一个任务并让epub构造函数(epub是一个类)使用UnZip()。Wait(),但这只是冻结了应用程序。我该怎么办?

编辑:这是我的相关代码:

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 :(得分:2)

基本上,您的问题似乎是:如何从构造函数中调用async方法?

简短的回答是,您不需要为您的班级创建async工厂方法。

更长的答案:正如您所注意到的,if you call Wait(), your code will block。您无法使用await,因为构造函数不能是async。如果你什么都不做,那么构造函数就会过早地返回。

这里的解决方案是使用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