关于UI C#中的Winform线程

本文关键字:Winform 线程 中的 UI 关于 | 更新日期: 2023-09-27 17:57:25

当我使用委托方法来运行我的方法以让UI刷新时,UI不会刷新。我想在方法运行时阻止UI冻结,我能做什么?

    private void SearchToolStripButton_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(new ThreadStart(StartMethod));
        t.Start();
    }
    private delegate void InvokeDelegate();
    public void StartMethod()
    {
        this.BeginInvoke(new InvokeDelegate(SearchData));
    }
    public void SearchData()
    {
        if (searchKeywordTextBox.Text == "")
        {
            MessageBox.Show("Please type the keyword!");
        }
        else
        {
            if (searchDateTimePicker.Checked == true)
            {
                switch (selectRangeComboBox.Text)
                {
                    case "Day": showDataToresultDataGridViewOnDay(searchKeywordTextBox.Text);
                        break;
                    case "Month": showDataToresultDataGridViewInMonth(searchKeywordTextBox.Text);
                        break;
                    case "Year": showDataToresultDataGridViewInYear(searchKeywordTextBox.Text);
                        break;
                    default: MessageBox.Show("Please select a Section");
                        break;
                }
            }
            else
            {
                showDataToresultDataGridView(searchKeywordTextBox.Text);
            }
        }
    }
    public void showDataToresultDataGridViewOnDay(string keyword)
    {
        DataGridView dayGrid = resultDataGridView;
        ShowResultDay day = new ShowResultDay();
        resultDataGridView.DataSource = day.ShowGridDay(searchDateTimePicker.Value.Day, searchDateTimePicker.Value.Month, searchDateTimePicker.Value.Year, keyword);
        resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records in " + searchDateTimePicker.Value.Day + "/" + searchDateTimePicker.Value.Month + "/" + searchDateTimePicker.Value.Year;
    }
    public void showDataToresultDataGridViewInMonth(string keyword)
    {
        DataGridView monthGrid = resultDataGridView;
        ShowResultMonth month = new ShowResultMonth();
        resultDataGridView.DataSource = month.ShowGridMonth(searchDateTimePicker.Value.Month, searchDateTimePicker.Value.Year, keyword);
        resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records in " + searchDateTimePicker.Value.Month + "/" + searchDateTimePicker.Value.Year;
    }
    public void showDataToresultDataGridViewInYear(string keyword)
    {
        DataGridView yearGrid = resultDataGridView;
        ShowResultYear year = new ShowResultYear();
        resultDataGridView.DataSource = year.ShowGridYear(searchDateTimePicker.Value.Year, keyword);
        resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records in " + searchDateTimePicker.Value.Year;
    }
    public void showDataToresultDataGridView(string keyword)
    {
        ShowAllData all = new ShowAllData();
        var results = all.ShowGirdAll(keyword);
        resultDataGridView.DataSource = results;
        resultLabel.Text = "Showing " + resultDataGridView.RowCount + " records";
    }

关于UI C#中的Winform线程

您应该了解一下BackgroundWorker类,它是专门为使WinForms中的多线程更容易而实现的。

那么我建议另一件事:
不要从后台线程打开消息框,而是在启动线程之前检查属性和字段,然后只在非ui线程中运行搜索。

后台工作人员使用示例:

// Initialization
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
// Start elaboration
bw.RunWorkerAsync(objectArgument);
void bw_DoWork(object sender, DoWorkEventArgs e)
{
   // do your work (we are in the background-thread)
   // when you have finished, set your results in the e.Result property
   // N.B. don't show anything because we are in the background-thread
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   // here we have finished the work (we are in the UI-thread)
   // result is set in e.Result property
   // N.B. check e.Error property before to get e.Result because
   //      if there's an error e.Result throws an exception
}

与本机Win32 API或MFC不同,Dot-net框架不支持多线程UI方法的*对控件的调用。因此,您不能在任何线程中创建UI控件(窗口)并从另一个线程调用它的方法和设置属性!(*在这里和下面-更新(刷新)UI上下文的UI方法。您可以从控件读取数据,但不能写入)顺便说一句,在本机环境中,这种调用也不能可靠地工作,有时会抛出管理不善的异常。。。但是托管环境不允许方法调用会导致异常!它只是"冻结"了一个这样的调用,而不做任何刷新操作。顺便说一句,该平台的这一功能不仅适用于后台线程。无论是调用BeginInvoke(从内置线程池),还是通过其他方式创建用户的非后台线程,都会遇到同样的问题。在您的特定情况下,我看不出有任何理由让两个或多个线程共享同一控件——这在数据安全方面也是危险的。通常,其他线程(通常是并行)用于完全不同的目的:用于任何长时间计算、数据库、文件和网络的I/O操作。当然,您也可以在其他线程中调用一些MessageBoxes。