简单的线程测试

时间:2010-11-05 14:50:24

标签: c# multithreading

我想了解更多关于线程的知识,并创建了一个改变标签背面颜色的小测试应用程序。

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

    //lblColor
    public Color theLabel
    {
        get { return this.lblColor.BackColor;  }
        set { this.lblColor.BackColor = value; }
    }

    //btnStart
    private void btnStart_Click(object sender, EventArgs e)
    {
        ThreadTest cColor = new ThreadTest();
        Thread tColor = new Thread(new ThreadStart(cColor.ChangeColor));

        tColor.Start();
    }
}

和...

public class ThreadTest
{
    public void ChangeColor()
    {
        Form1 foo = new Form1();
        while (true)
        {
            foo.theLabel = Color.Aqua;
            foo.theLabel = Color.Black;
            foo.theLabel = Color.DarkKhaki;
            foo.theLabel = Color.Green;
        }
     }
}

唯一的问题是为什么我不能让这段代码工作?我可以看到ChangeColor中的代码运行但标签的颜色不会改变。

4 个答案:

答案 0 :(得分:5)

乍一看,您正在构建一个新表单

Form1 foo = new Form1(); 
在ThreadTest内部并且从不显示表单,我猜您是否打算使用btnStart更改表单上的表单颜色?您有两个选项,可以将表单传递给ParameterizedThreadStart,也可以重新编写代码以仅对现有表单进行操作。

此外,根据编写的代码,您可能需要使用Invoke来更新表单的状态,因为您无法让工作线程更新UI。我会调整你的代码并发布一个修改过的例子,如果有人没有打败我。

修改

在这种情况下,你不需要调用......但这是我认为你想要的......

private void btnStart_Click(object sender, EventArgs e)
{
  ThreadTest cColor = new ThreadTest();
  Thread tColor = new Thread(new ParameterizedThreadStart(cColor.ChangeColor));

  tColor.Start(this);
}

public class ThreadTest
{
  public void ChangeColor(Object state)
  {
    Form1 foo = (Form1) state;
    while (true)
    {
      foo.theLabel = Color.Aqua;
      foo.theLabel = Color.Black;
      foo.theLabel = Color.DarkKhaki;
      foo.theLabel = Color.Green;
    }
  }
} 

此外,将工作线程设置为后台线程非常重要,否则当您关闭表单时,线程将保持该应用程序打开。

tColor.IsBackground = true;

附加示例

一个稍微不同的例子是让多个线程尝试更新相同的值,看看它们是如何交错的...简单的片段让球滚动。

private void btnStart_Click(object sender, EventArgs e)
{
  CreateBackgroundColorSetter(Color.Aqua);
  CreateBackgroundColorSetter(Color.Black);
  CreateBackgroundColorSetter(Color.DarkKhaki);
  CreateBackgroundColorSetter(Color.Green);
}


private void CreateBackgroundColorSetter(Color color)
{
  var thread = new Thread(() =>
                            {
                              while (true)
                              {
                                theLabel = color;
                                Thread.Sleep(100);
                              }
                            });
  thread.IsBackground = true;

  thread.Start();
}

答案 1 :(得分:3)

你有2个问题

a)您不应该从其他线程更新UI

b)即使您被允许这样做,您也需要告诉UI重新绘制

这些都是非常重要的问题

如果您只是尝试使用线程,那么使用Debug.WriteLine来查看后台线程正在做什么

如果您确实需要在后台更新UI,请查找BeginInvoke和InvokeNeeded

答案 2 :(得分:1)

如果你真的需要在GUI应用程序中进行线程化,那么你将需要BackgroundWorker或类似的东西。如上所述,其他线程无论如何都无法更新GUI,因此显示的示例是一个更好的模型,用于将长时间运行的工作项移出主线程。

  

BackgroundWorker类允许您   在一个单独的,   专用线程。耗时的   下载和数据库等操作   交易可能会导致您的用户   界面(UI)看起来好像它   他们已经停止了回应   运行。当您需要响应式UI时   你面临着长时间的拖延   与此类操作相关联的   BackgroundWorker类提供了一个   方便的解决方案。

答案 3 :(得分:0)

如果您想要使用线程进行实验,只需创建一个控制台应用程序并使用谷歌“线程教程c#”来获得一些示例。

关于线程和winform,您可以查看以下链接,了解在从另一个线程访问win form属性之前应该考虑的事项

In WinForms, why can't you update UI controls from other threads?