C# WinForm跨线程访问控件

.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性,会提示错误“跨线程操作无效“。

提供几种方法解决这个问题

1. 设置CheckForIllegalCrossThreadCalls为False

CheckForIllegalCrossThreadCalls为全局静态变量,设置为False后程序就不检查跨线程的调用是否合法

2、delegate委托

假设需要在更新控件Label1的Text

private void button1_Click(object sender, EventArgs e)
{
    Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel1));
    thread1.Start("更新Label");
}         

(1)搭配invoke

private void UpdateLabel1(object str)
{
    if (label2.InvokeRequired)
    {
        // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
        Action<string> actionDelegate = (x) => { this.Label1.Text = x.ToString(); };
        // 或者
        // Action<string> actionDelegate = delegate(string txt) { this.Label1.Text = txt; };
        this.Label1.Invoke(actionDelegate, str);
    }
    else
    {
        this.Label1.Text = str.ToString();
    }
}

(2)搭配BeginInvoke

private void UpdateLabel1(object str)
{
    if (label2.InvokeRequired)
    {
        // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
        Action<string> actionDelegate = (x) => { this.Label1.Text = x.ToString(); };
        // 或者
        // Action<string> actionDelegate = delegate(string txt) { this.Label1.Text = txt; };
        this.Label1.BeginInvoke(actionDelegate, str);
    }
    else
    {
        this.label2.Text = str.ToString();
    }
}

Invoke方法是同步的, 它会等待工作线程完成,

BeginInvoke方法是异步的, 它会另起一个线程去完成工作线程

3、BackgroundWorker组件

private void button1_Click(object sender, EventArgs e)
{
    using (BackgroundWorker bw = new BackgroundWorker())
    {
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerAsync("Tank");
    }         
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{       
    // 这里是后台线程, 是在另一个线程上完成的
    // 这里是真正做事的工作线程
    // 可以在这里做一些费时的,复杂的操作
    Thread.Sleep(5000);
    e.Result = e.Argument + "工作线程完成";
}

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了 
    this.Label1.Text = e.Result.ToString(); 
}

转载于:https://my.oschina.net/ZhangYaqing/blog/1547730

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页