如何在单个线程中调用多个控件?

时间:2017-12-10 13:11:38

标签: c# multithreading

我从数据库中获取数据,并根据父comboBox值将其同时绑定到3个不同的组合框。以下是示例,我有三个名为

的组合框
i. comboBoxBranch
ii. comboBoxClass
iii. comboBoxSection

comboBoxClass的值是在所选分支的基础上从数据库中获取的,同样,comboBoxSection的值是在所选分支和所选类的基础上获取的。所以绑定的顺序是(ComboBoxBranch)然后是comboBoxClass,然后是comboBoxSection。

现在为了实现这一点,我使用单独的线程来调用GetBranches()方法,以下面的方式将数据与comboboxBranch绑定。

    private void GetBranches() (This is working perfectly fine)
    {     
        if (comboBoxBranches.InvokeRequired)
        {
            comboBoxBranches.BeginInvoke(((MethodInvoker) delegate
            {
                comboBoxBranches.DataSource = _schoolManagementSystemServiceClient.GetBranches();
                comboBoxBranches.ValueMember = "BranchId";
                comboBoxBranches.DisplayMember = "BranchName";

            }));
        }  

现在问题出现了我应该如何将数据与comboxClass和comboBoxSection的其他两个组合框绑定,我应该使用另一个线程,因为我正在使用Getbranch方法,或者有任何其他干净的方法来实现这一点。以下是我在comboBoxBranches的comboBoxBranches_SelectedValueChanged()事件方法中调用的GetClasses方法。

private void comboBoxBranches_SelectedValueChanged(object sender, EventArgs e)
     {
         Thread thread=new Thread(GetClasses());
         thread.start();  
     }
 private void GetClasses()// in this method how should I achieve invoking  for multiple controls? What should I do here?
    {
           if (InvokeRequired)
        {
            comboBoxBranches.BeginInvoke(((MethodInvoker) delegate
            {
                Branch branch = comboBoxBranches.SelectedItem as Branch;
            }));
            comboBoxClasses.BeginInvoke((MethodInvoker) delegate
            {
                comboBoxClasses.DataSource = _schoolManagementSystemServiceClient.GetClasses(branch.BranchId);
                comboBoxClasses.ValueMember = "ClassId";
                comboBoxClasses.DisplayMember = "ClassName";
            });              
        }
    }

相同的方法是comboxBoxSections,其值基于ComboBoxBranches和comboBoxClasses?我是多线程的新手。

1 个答案:

答案 0 :(得分:2)

调用意味着等待UI线程空闲,然后切换到UI线程并执行一些操作。因此,必须在调用之前执行长时间运行的任务(例如,从数据库查询数据)。

今天,实现此目标的首选方法是使用async / await。

private async void comboBoxBranches_SelectedValueChanged(object sender, EventArgs e)
{
    //  We are in the UI thread and can access the controls directly.
    Branch branch = comboBoxBranches.SelectedItem as Branch;

    var classes = await Task.Run(
        // This runs in a new thread. At this point the UI is not blocked.
        () => _schoolManagementSystemServiceClient.GetClasses(branch.BranchId)
    );
    // Here the thread joins the UI thread and returns the classes.

    // We are in the UI thread again. No need for Invoke.
    comboBoxClasses.DataSource = classes;
    comboBoxClasses.ValueMember = "ClassId";
    comboBoxClasses.DisplayMember = "ClassName";
}

请注意方法标题中的关键字async。它告诉C#以特殊方式处理这个方法。在幕后,C#完全重写了这种方法,使魔法发生并隐藏了所涉及的复杂性。

要理解它是如何工作的,你可以想象C#将等待任务之后的行(带有comboBoxClasses的3行)放入回调方法中。

Async in depth (Microsoft)中所述,您还应该重写GetClasses以异步工作并返回Task<T>对象,而不是在此处启动新线程。

var classes = await _schoolManagementSystemServiceClient.GetClassesAsync(branch.BranchId);

请参阅:Asynchronous programming (Microsoft)