关于UI C#中的Winform线程

时间:2011-05-22 13:32:58

标签: c# winforms

当我使用委托方法运行我的方法以便让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";
    }

2 个答案:

答案 0 :(得分:3)

你应该看看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
}

答案 1 :(得分:0)

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