首页 > 解决方案 > 避免在不使用 Application.DoEvents() 的情况下阻塞表单

问题描述

我的程序在计时器事件中显示时间,并button启动一个函数,该函数不断读取文件的内容,直到达到 50 行。

测试文件是由一个不同的文件创建的process,它偶尔会向它附加一些行。

如何修改程序以避免在执行期间阻塞表单?

WinForm Application UI Hangs during Long-Running Operation相比,不同之处在于调用的函数必须更新表单的某些元素。

而且我不想使用 Application.DoEvents(),我的程序中有数百行 Application.DoEvents(),有时它们会造成混乱。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    void Timer1Tick(object sender, EventArgs e)
    {
        UpdateTime();           
    }

    void UpdateTime()
    {
        DateTime dt = DateTime.Now;
        textBox1.Text = dt.ToString("hh:mm:ss");
    }


    void BtnRunClick(object sender, EventArgs e)
    {
        int nlines = 0;
        while(nlines < 50) {
            nlines = listBox1.Items.Count;
            this.Invoke(new Action(() => ReadLinesFromFile()));         
            Thread.Sleep(1000);
        }
    }   

    void ReadLinesFromFile()
    {
        string sFile = @"D:\Temp1\testfile.txt";
        string[] lines = File.ReadAllLines(sFile);
        listBox1.Items.Clear();
        foreach(string line in lines) {
            listBox1.Items.Add(line);
            listBox1.SelectedIndex = listBox1.Items.Count - 1;
        }
    }
}

标签: c#winforms

解决方案


IO 操作的异步方法将在同一个 UI 线程上执行所有操作而不阻塞它。

private async void BtnRunClick(object sender, EventArgs e)
{
    int nlines = 0;
    while(nlines < 50) {
        nlines = listBox1.Items.Count;
        await ReadLinesFromFile();
        await Task.Delay(1000);
    }
}   

private async Task ReadLinesFromFile()
{
    var file = @"D:\Temp1\testfile.txt";
    string[] lines = await ReadFrom(file);

    listBox1.Items.Clear();
    foreach(string line in lines) {
        listBox1.Items.Add(line);
        listBox1.SelectedIndex = listBox1.Items.Count - 1;
    }
}

private async Task<string[]> ReadFrom(string file)
{
    using (var reader = File.OpenText(file))
    {
        var content = await reader.ReadToEndAsync();
        return content.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
    }
}

推荐阅读