在C#的多線程訪問(wèn)中,在線程間的相互訪問(wèn)時(shí)因?yàn)榫€程安全問(wèn)題有訪問(wèn)限制,在創(chuàng)建一般線程時(shí),對(duì)于界面元素訪問(wèn)時(shí)這樣的問(wèn)題比較常見(jiàn)。
比如,創(chuàng)建一個(gè)form1,上面放置一個(gè)textbox控件,創(chuàng)建一個(gè)線程去訪問(wèn)textbox,界面如下:
按鈕buuton1的代碼:
private void button1_Click(object sender, EventArgs e)
{
var thread1 = new System.Threading.Thread(Func1);
thread1.Start();
}
就是簡(jiǎn)單地創(chuàng)建一個(gè)線程,線程里面運(yùn)行的func1代碼:
private void Func1()
{
for(int i = 0; i < 5; i++)
{
textBox1.Text = textBox1.Text+ $"線程{Thread.CurrentThread.ManagedThreadId}執(zhí)行{i}."+Environment.NewLine;
}
}
運(yùn)行,點(diǎn)擊button1按鈕系統(tǒng)會(huì)報(bào)錯(cuò):
意思是說(shuō):線程間操作無(wú)效:從不是創(chuàng)建控件“textbox1”的線程訪問(wèn)它,這是不允許的。
線程存在安全保護(hù)機(jī)制,并不能隨意訪問(wèn),因?yàn)檫@樣存在沖突的可能。
解決這個(gè)問(wèn)題,最直接的方法是在界面初始化后去掉控件的跨線程非法訪問(wèn)屬性,即將Control.CheckForIllegalCrossThreadCalls屬性設(shè)置為false即可。
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
這樣結(jié)果就出來(lái)了。
一般情況下,還是不要設(shè)置Control.CheckForIllegalCrossThreadCalls的屬性,那么怎樣可以達(dá)到修改textbox1的值呢?
可以通過(guò)委托來(lái)解決。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var thread1 = new System.Threading.Thread(Func1);
thread1.Start();
}
public void SetText(string SText)
{
textBox1.Text = textBox1.Text + SText + Environment.NewLine;
}
private void Func1()
{
string Str = "";
for (int i = 0; i < 5; i++)
{
Str= $"線程{Thread.CurrentThread.ManagedThreadId}執(zhí)行{i}."+Environment.NewLine;
if (textBox1.InvokeRequired)
{
Action SetText111 = delegate { SetText(Str); };
textBox1.Invoke(SetText111);
}
else
{
textBox1.Text = Str;
}
}
}
}
這樣也可以達(dá)到目的,或者直接寫(xiě)更簡(jiǎn)單:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var thread1 = new System.Threading.Thread(Func2);
thread1.Start();
}
private void Func2()
{
textBox1.Invoke(() =>
{
for (int i = 0; i < 5; i++)
{
textBox1.Text = textBox1.Text+ $"線程{Thread.CurrentThread.ManagedThreadId}執(zhí)行{i}." + Environment.NewLine;
}
});
}
}
效果也是一樣的。
在C#中,需要注意Invoke和begininvoke的區(qū)別。
control.invoke(參數(shù)delegate):在擁有此控件的基礎(chǔ)窗口句柄的線程上執(zhí)行指定的委托,注意是同步。
control.begininvoke(參數(shù)delegate):在創(chuàng)建控件的基礎(chǔ)句柄所在線程上異步執(zhí)行指定委托,注意這里執(zhí)行的是異步。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-407130.html
在跨線程請(qǐng)求時(shí),常檢驗(yàn)textBox1.InvokeRequired屬性,即是否跨線程請(qǐng)求。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-407130.html
到了這里,關(guān)于C#線程間操作無(wú)效:從不是創(chuàng)建控件“textbox1”的線程訪問(wèn)它的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!