无法异步打开类构造函数内部的文件

时间:2018-07-25 19:27:03

标签: c# uwp

我是C#的新手。我正在尝试使用StorageFile类打开一对CSV文本文件,但是我需要在类构造函数(不能异步)中完成它:

private async Task SetupFileAccess()
{
    MainCarDataStorageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///leaf.csv"));
    var MainCarDataInputStream = await MainCarDataStorageFile.OpenReadAsync();
    var MainCarDataClassicStream = MainCarDataInputStream.AsStreamForRead();
    MainCarDataStream = new StreamReader(MainCarDataClassicStream);

    await MainCarDataStream.ReadLineAsync(); //clear header line from csv

    LookupTableStorageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Full_Charge_To_Empty.csv"));
    var LookupTableInputStream = await LookupTableStorageFile.OpenReadAsync();
    var LookupTableClassicStream = LookupTableInputStream.AsStreamForRead();
    LookupTableDataStream = new StreamReader(LookupTableClassicStream);

    await LookupTableDataStream.ReadLineAsync(); //clear header line from csv
}

然后我在该函数上调用Wait()以阻止执行。

问题是当我到达第二个OpenReadAsync()函数调用以打开到第二个文件的流(Full_Charge_to_Empty.csv)时,该程序会永远搅动。没有崩溃,没有进展。

似乎我只能访问打开的第一个文件。如果我注释掉第一个文件访问(leaf.csv),则可以访问第二个文件。如果切换位置(leaf.csv已打开2号),则无法打开leaf.csv。

我感觉对于这些文件访问的工作方式肯定有些不了解...是因为我对第一个文件(leaf.csv)的访问正在占用某种类型的资源吗?感谢帮助!

1 个答案:

答案 0 :(得分:0)

问题是您试图强制异步函数在构造函数中同步完成;这不会很好地结束。正确的方法是使用异步工厂方法来预先加载工作,然后返回填充的对象。例如:

<AlternatingItemTemplate>
    <tr><td><%# Eval("DayName") %></td></tr>
</ItemTemplate>

使用它:

class Test
{
    // Make constructor private so no-one can create it
    private Test()
    { }

    // Simple string properties that can't be async
    public string Text1 { get; private set; }
    public string Text2 { get; private set; }

    // Async factory method that can do async things
    public static async Task<Test> CreateAsync()
    {
        var result = new Test();
        result.Text1 = await LoadFile("file1.txt");
        result.Text2 = await LoadFile("file2.txt");
        return result;
    }

    // Helper function
    static async Task<string> LoadFile(string filename)
    {
        var file = await Package.Current.InstalledLocation.GetFileAsync(filename);
        var size = (await file.GetBasicPropertiesAsync()).Size;
        var reader = new DataReader(await file.OpenReadAsync());
        reader.UnicodeEncoding = UnicodeEncoding.Utf8;
        await reader.LoadAsync((uint)size);

        // assumes single-byte UTF codepoints, eg ASCII
        return reader.ReadString((uint)size);
    }
}