等到文件完全读取,然后在富文本框中显示结果

时间:2014-02-17 10:20:10

标签: c# .net winforms task async-await

我知道你不能让GUI控件在一个单独的线程中工作。在我的表单加载上,我想从文本文件中读取,然后在富文本框中显示内容。我在一个单独的线程中进行阅读,但由于最终我希望这个文本出现在我的Rich Textbox上,我的窗口仍然会冻结,而且我的加载微调器没有动画。

private async void PreviewFileForm_Load(object sender, EventArgs e)
{
    string fileName = Path.GetFileName(this.filePath);
    lblFileName.Text = fileName;
    richtxtboxPreview.Visible = false;
    string fileContents = await ReadFileAsync(this.filePath);
    richtxtboxPreview.Text = fileContents;
    richtxtboxPreview.Visible = true;
    spinnerLoadFile.Visible = false;
}

async Task<string> ReadFileAsync(string filePath)
{
    string s = String.Empty;
    await Task.Run(() =>
    {           
        using (StreamReader sr = File.OpenText(filePath))
        {
            s = sr.ReadToEnd();
        }
    });
    return s;
}

我可以做什么,以便我的加载栏旋转以指示等待文件被读取,然后富文本框显示结果?

1 个答案:

答案 0 :(得分:1)

您可以使用异步文件I / O执行此操作。 Here's a Microsoft sample.

因此,如果您实现这样的异步文件阅读器(将编码更改为适合您的文本文件的类型;此代码将从上面链接的Microsoft示例中逐字复制):

private async Task<string> readFileAsync(string filePath)
{
    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Open, FileAccess.Read, FileShare.Read,
        bufferSize : 4096, useAsync : true))
    {
        StringBuilder sb = new StringBuilder();

        byte[] buffer = new byte[0x1000];
        int numRead;
        while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            // Use correct encoding here; maybe you need Encoding.UTF8
            string text = Encoding.Unicode.GetString(buffer, 0, numRead);
            sb.Append(text);
        }

        return sb.ToString();
    }
}

你应该能够像现在一样调用它。

但是,在从Load事件中做事时,我有时会发生奇怪的事情。

在某些情况下,我通过将代码放入一个单独的方法并使用BeingInvoke()从Load方法调用它来解决这些问题,例如:

private void PreviewFileForm_Load(object sender, EventArgs e)
{
    this.BeginInvoke(new Action(doIt));
}

private async void doIt()
{
    string fileName = Path.GetFileName(this.filePath);
    lblFileName.Text = fileName;
    richtxtboxPreview.Visible = false;
    string fileContents = await ReadFileAsync(this.filePath);
    richtxtboxPreview.Text = fileContents;
    richtxtboxPreview.Visible = true;
    spinnerLoadFile.Visible = false;
}