日期:2014-05-18  浏览次数:21090 次

后台线程可不可以访问UI控件?
书上说:对于每个控件,都只能从创建该控件的线程中调用方法。也就是说,如果有一个后台线程,就不能直接在这个线程访问这个线程的UI控件。
可是这样能访问控件啊?
C# code
public void CountTime()
{
    while (true)
    {
        textBox1.Text = DateTime.Now.ToLongTimeString();
    }
}

private void Form1_Load(object sender, EventArgs e)
{
    Thread currentTimeThread = new Thread(new ThreadStart(CountTime));
    currentTimeThread.IsBackground = true;
    currentTimeThread.Start();
}


------解决方案--------------------
需要线程同步。可以用控件的Invoke或BeginInvoke方法。
例如
你可以这样编写按钮事件
C# code
public void Button1_Clicked(object s ,EventArgs e)
{
    new Thread((ThreadStart)delegate
    {
        this.Invoke((EventHandler)delegate{this.Text = "线程修改了UI的标题。"});
    }).Start();//创建线程并启动
}

------解决方案--------------------
C# code
//需要用委托
private delegate void myInvoke();
        public void CountTime()
        {
            myInvoke mi = new myInvoke(setText);
            while (true)
            {
                this.Invoke(mi);
            }
        }
        private void setText()
        {
            textBox1.Text = DateTime.Now.ToLongTimeString();
        }

------解决方案--------------------
构造函数,设置Form.CheckForIllegalCrossThreadCalls = true;
------解决方案--------------------
没说你的不正确。我是给你演示多线程操作、以及跨线程访问资源外加一个匿名方法使用。
------解决方案--------------------
同一个线程访问
不是说不能使用线程访问。

如果你不使用锁的话 会照成线程串值
------解决方案--------------------
探讨
书上说:对于每个控件,都只能从创建该控件的线程中调用方法。也就是说,如果有一个后台线程,就不能直接在这个线程访问这个线程的UI控件。
可是这样能访问控件啊?

C# code
public void CountTime()
{
while (true)
{
textBox1.Text = DateTime.Now.ToLongTimeString()……

------解决方案--------------------
用委托 可以访问控件
------解决方案--------------------
这个测试是这样的:
C# code
using System;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Load += new EventHandler(Form1_Load);
        }

        public void CountTime()
        {
            while (true)
            {
                if (textBox1.InvokeRequired)
                    textBox1.Invoke(new Action(() => { textBox1.Text = DateTime.Now.ToLongTimeString(); }));
                else
                    textBox1.Text = DateTime.Now.ToLongTimeString();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Thread currentTimeThread = new Thread(new ThreadStart(CountTime));
            currentTimeThread.IsBackground = true;
            currentTimeThread.Start();
        }
    }
}