C#中的线程控件 [英] Threading controls in C#

查看:80
本文介绍了C#中的线程控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个按钮startbtn和stopbtn,一个组合框和一个列表框。组合框收集项目是TRUE& 假。以下是,



I have two buttons startbtn and stopbtn, a combobox and a listbox. The combobox collection items are "TRUE" & "FALSE". below is the,

private void startbtn_Click(object sender, EventArgs e)
        {
            int i = 0;
            while (comboBox1.Text == "TRUE")
            {
                
                i = i + 1;
                listBox1.Items.Add(i.ToString());
            }
        }




private void stopbtn_Click(object sender, EventArgs e)
        {
            comboBox1.Text = "FALSE";
        }





我们都知道,上面的代码正在执行

1我们无法将组合框文本从TRUE更改为FALSE

2.我们无法单击stopbtn来终止该过程。

3.在整个过程完成之前,Listbox1不会在每个循环时间更新(除非我使用的是背景类)。



如何使用线程来克服这3个问题?我们需要分别对每个控件和事件处理程序进行线程化吗?我不太明白线程多个事件处理程序如何。我正在学习即将开展的项目的线程概念。这是我必须开始的地方。请帮我理解



我尝试过:



http ://www.c-sharpcorner.com/article/introduction-to-multithreading-in-C-Sharp/



The thing is we all know that while the above code is executing
1. we cannot change the combobox text from "TRUE" to "FALSE"
2. we cannot click on stopbtn to terminate the process.
3. Listbox1 will not get updated at each loop time until the process is completed (unless i am using a backgrounder class).

how to use threading to overcome these 3 issues? do we need to thread each controls and event handlers seperately? i can't quite understand how thread multiple event handlers. I am learning the threading concept for my upcoming project. Here is where i have to start. Please help me to understand

What I have tried:

http://www.c-sharpcorner.com/article/introduction-to-multithreading-in-C-Sharp/

推荐答案

这是一个使用Windows窗体的解决方案。我尽量保持尽可能接近你的代码,虽然Foothill的解决方案在我看来更好,你可以通过改变一行代码来使用它:



Here is a solution using Windows Forms. I tried to stay as close to your code as possible, although Foothill's solution is better in my opinion, and you could use it by changing a single line of code:

Dispatcher.Invoke(() => listBox1.Items.Add(i.ToString()));





应更改为:





Should be changed to:

this.Invoke((MethodInvoker)(() => listBox1.Items.Add(i.ToString())));





是的,我们正在使用lambda表达式。如果你不熟悉它们,你应该阅读lambda表达式和匿名方法这里 ,并此处



这是我的解决方案(保持尽可能接近您的代码):



Yes, we're using lambda expressions. If you're not familiar with them, you should read up on lambda expressions and Anonymous Methods here, and here.

Here's my solution (keeping as close to your code as possible):

private void startbtn_Click(object sender, EventArgs e)
{
    String comboBox1Text = "";

    this.Invoke((MethodInvoker)(() => comboBox1Text = comboBox1.Text));
    new System.Threading.Thread(() =>
    {
        int i = 0;
        while (comboBox1Text.Equals("TRUE"))
        {
            i = i + 1;
            this.Invoke((MethodInvoker)(() => 
            { 
                listBox1.Items.Add(i.ToString());
                comboBox1Text = comboBox1.Text;
            }));
        }
    }).Start();
}

private void stopbtn_Click(object sender, EventArgs e)
{
    comboBox1.Text = "FALSE";
}





这样做 - 我测试了它。让我解释一下它的工作原理。



正如Griff上面所说,你只能从创建它们的线程更新用户界面(UI)元素。在Windows窗体中,所有控件都知道哪个线程创建了它们,甚至Form也是一个控件。您可以询问控件是否从使用control.invokeRequired(返回bool)创建它的线程访问它。如果返回true,则需要调用控件,或者调度代码以在UI线程上运行。您可以通过调用control.Invoke()来完成此操作。花一点时间,阅读control.invoke的内容这里



有很多不同的方法可以使用control.invoke(),但是我在这个例子中使用的方法 - 虽然可能不是最好的(我通常设置)一个辅助函数来处理UI更新并在lambda表达式中传递它。它使你的代码更清晰/更可读),在这个例子中工作。



如果我错过了什么,或者你有任何问题,请随时询问。



- Pete



This works - I tested it. Let me explain a little about why it works.

As Griff said above, you can only update user interface (UI) elements from the thread that created them. In Windows forms, all controls "know" which thread created them, and even a Form is a control. You can ask a control if you are accessing it from the thread that created it using control.invokeRequired (returns a bool). If it returns true, then you need to "Invoke" the control, or schedule code to run on the UI thread. You do this by calling control.Invoke(). Take a minute, and read up on what control.invoke does here.

There are many different ways to use control.invoke(), but the one I used in this example - while maybe not the best (I usually set up a helper function to handle UI updates and pass it code in a lambda expression. It makes your code clearer / more readable), works in this example.

If I missed anything,or you have any questions, please feel free to ask.

- Pete


线程不难组织,但该代码需要修改,因为除了创建它们的线程(UI线程)之外,您无法访问控件。因此,循环终止/线程退出测试不能直接涉及组合框。不幸的是,这也适用于ListBox - 它需要被调用到UI线程以添加你的项目。

话虽如此,这并不难:

Threading isn't difficult to organise, but that code would need modification, because you can't access controls except on the thread on which they were created - the UI thread. So your loop termination / thread exit test cannot involve the combobox directly. Unfortunately, that also applies to the ListBox as well - it needs to be Invoked onto teh UI thread in order to add your items.
Having said that, it's not difficult to do:
private bool endTheLoop = false;
private void startbtn_Click(object sender, EventArgs e)
    {
    endTheLoop = false;
    BackgroundWorker work = new BackgroundWorker();
    work.DoWork += work_DoWork;
    work.RunWorkerAsync();
    }

void work_DoWork(object sender, DoWorkEventArgs e)
    {
    int i = 0;
    while (!endTheLoop)
        {

        i = i + 1;
        listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add(i.ToString()); });
        }

    }
private void stopbtn_Click(object sender, EventArgs e)
    {
    endTheLoop = true;
    }


如果你想利用lambda表达式,这可能也适合你。

注意:这是为了与WPF一起使用

If you want to take advantage of lambda expressions, this might also work for you.
Note: this was written to use with WPF
public bool Stop { get; set; }
private void startbtn_Click(object sender, EventArgs e)
{
  Thread worker = new Thread(() =>
   {
     int i = 0;

     while (!Stop)
     {
       Dispatcher.Invoke(() => listBox1.Items.Add(i.ToString()));
       ++i;
     }
   }
  );

  worker.Start();
}
private void stopbtn_Click(object sender, EventArgs e)
{
  Stop = true;
}


这篇关于C#中的线程控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆