1

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

    }
4

1 に答える 1

2

async基本的に、あなたの質問は次のようです:コンストラクターからメソッドを呼び出すにはどうすればよいですか?

簡単に言えば、そうではなく、代わりにasyncクラスのファクトリ メソッドを作成します。

より長い答え: お気づきのように、 を呼び出すWait()と、コードは をブロックします。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 のおよび コンストラクターに関する記事asyncを参照してください。

于 2013-06-11T16:37:56.973 に答える