跨线程访问控件二

我第一次碰到跨线程访问可视化控件的问题是在写串口通讯程序的时候。

我不会再举出那个例子,有点麻烦。我们用下面这个例子,制造这个现象。

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.Threading;

 
 

namespace WindowsFormsApplication6

{

public
partial
class
Form1 : Form

{

public Form1()

{

InitializeComponent();

}

 
 

private
void button1_Click(object sender, EventArgs e)

{

ThreadStart ts = new
ThreadStart(PrintLable);

Thread th = new
Thread(ts);

th.Start();

 
 

 
 

}

 
 

private
void PrintLable()

{

this.label1.Text = 跨线程访问控件了!;

}

}

}


 
 


在.NET 2.0之前是允许跨线程访问可视化控件的,后续就不允许了,可能是基于界面跨线程访问容易造成混乱的原因吧。比如界面在刷新,突然插入个新的程序要更改界面的数据,容易造成混乱。

最简单的解决办法就是添加一条语句,加粗的那一句。

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.Threading;

 
 

namespace WindowsFormsApplication6

{

public
partial
class
Form1 : Form

{

public Form1()

{

Control.CheckForIllegalCrossThreadCalls = false;

InitializeComponent();

}

 
 

private
void button1_Click(object sender, EventArgs e)

{

ThreadStart ts = new
ThreadStart(PrintLable);

Thread th = new
Thread(ts);

th.Start();

 
 

 
 

}

 
 

private
void PrintLable()

{

this.label1.Text = 跨线程访问控件了!;

}

}

}

但是官方并不鼓励我们这么做,要不他们也不会费这么大劲了。

窗体是由UI线程创建的,这个UI线程拥有一个消息队列和相应的操作函数,负责接收操作系统发过来的各种消息并做处理,比如鼠标点击,键盘输入等等。

官方提供了相应的法案,把对可视化控件的访问转有UI线程负责。

Control.Invoke 同步方式

Control.BeginInvoke 异步方式

 
 

 
 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.Threading;

 
 

namespace WindowsFormsApplication6

{

public
partial
class
Form1 : Form

{

public
delegate
void
MyInvoke();

public Form1()

{

InitializeComponent();

}

 
 

private
void button1_Click(object sender, EventArgs e)

{

MyInvoke myIvoke = new
MyInvoke(PrintLable);

label1.Invoke(myIvoke);

}

 
 

private
void PrintLable()

{

this.label1.Text = 跨线程访问控件了!;

}

}

}

 
 

 
 

 
 

跨线程访问

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.Threading;

 
 

namespace test

{

public
partial
class
Form1 : Form

{

public Form1()

{

InitializeComponent();

}

static
int i;

 
 

private
void button1_Click(object sender, EventArgs e)

{

Thread th = new
Thread(new
ParameterizedThreadStart(showmsg) );

th.Start(“button1”);

}

 
 

void showmsg(Object s)

{

if(this.textBox1.InvokeRequired)

{

mydelegate d = show;

this.textBox1.Invoke(d,s);

}

else

{

show(s.ToString());

}

 
 

}

 
 

delegate
void
mydelegate(string s);

void show(string s)

{

this.textBox1.AppendText(s.ToString() + “\r\n”);

this.textBox1.AppendText(i.ToString() + “\r\n”);

i++;

}

 
 

private
void button2_Click(object sender, EventArgs e)

{

showmsg(“button2”);

}

}

}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注