詳解C#中線程傳參,返回值和多線程沖突問題的解決
在C#中,開啟一個(gè)線程很容易。
Thread Th1= new Thread(func); Th1.Start(); private void func(object Obj) { //處理代碼 }
很多情況下,我們是需要對線程進(jìn)行傳遞參數(shù)的,這個(gè)也簡單。
1、線程的單一參數(shù)傳遞
private void button1_Click(object sender, EventArgs e) { Thread Th1= new Thread(func); Th1.Start("CSDN"); Thread.Sleep(500); } private void func(object Obj) { string Str = Obj as string; textBox1.BeginInvoke(new Action(() => { textBox1.Text = $"傳入的參數(shù):{Str}"; })); }
2、線程的多參數(shù)傳遞以及返回值
上面的例子是單一的參數(shù),參數(shù)要求是對象,使用的時(shí)候進(jìn)行了拆箱,根據(jù)上面的例子對于多參數(shù),可以使用中間對象來處理,就是在中間對象中放置參數(shù)和獲取處理后的結(jié)果。
private void button1_Click(object sender, EventArgs e) { FinancialInfo FI=new FinancialInfo(); FI.PersonName = "CSDN"; FI.PersonDeposit = 123; Thread Th1 = new Thread(FI.ThreadChangeFinanceialInfo); Th1.Start(); Thread.Sleep(500); textBox1.Text=FI.PersonName+Environment.NewLine+FI.PersonDeposit.ToString(); } private class FinancialInfo { private string Name=string.Empty; private int Deposit=0; public string PersonName { get { return Name; } set { Name = value; } } public int PersonDeposit { get { return Deposit; } set { Deposit = value; } } public void ThreadChangeFinanceialInfo() { this.Name = this.Name + " | C#"; this.Deposit = this.Deposit + 100; }
3、多線程可能引起的沖突
多線程在處理同一對象時(shí)容易引起潛在的沖突,這個(gè)顯而易見,例如:
private void button1_Click(object sender, EventArgs e) { FinancialInfo FI = new FinancialInfo(); FI.PersonName = "CSDN"; FI.PersonDeposit = 123; Thread Th1 = new Thread(FI.ThreadAdd); Thread Th2 = new Thread(FI.ThreadReduce); Th1.Start(); Th2.Start(); Thread.Sleep(5000); textBox1.Text = textBox1.Text + FI.PersonName +"|"+FI.PersonDeposit.ToString()+Environment.NewLine; } private class FinancialInfo { private string Name=string.Empty; private int Deposit=0; public string PersonName { get { return Name; } set { Name = value; } } public int PersonDeposit { get { return Deposit; } set { Deposit = value; } } public void ThreadAdd() { for (int i = 0; i < 1000000; i++) { this.Deposit = this.Deposit + 1; } } public void ThreadReduce() { for (int i = 0; i < 1000000; i++) { this.Deposit = this.Deposit - 1; } } }
顯示結(jié)果:
按道理, FI.PersonDeposit的值是123,加了1000000,也減了1000000,那么最終的結(jié)果應(yīng)該還是123,為什么會是這樣呢?
這就是多線程在處理同一對象時(shí)所產(chǎn)生的沖突了,產(chǎn)生的就是所謂的“臟數(shù)據(jù)”。
上面的代碼因?yàn)榈却€程執(zhí)行完,進(jìn)行了休眠,可以使用Task來寫更簡單。
var task1 = new Task(FI.ThreadAdd); var task2 = new Task(FI.ThreadReduce); task1.Start(); task2.Start(); Task.WaitAll(task1,task2);
Task是比Thread更加高級的概念,一個(gè)Task至少包含一個(gè)Thread。
解決上面的沖突就是對可能引起沖突的對象進(jìn)行加鎖判斷。
完整代碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Text; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace MultiThread { public partial class Form3 : Form { private static readonly object LockObj=new object(); public Form3() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { FinancialInfo FI = new FinancialInfo(); FI.PersonName = "CSDN"; FI.PersonDeposit = 123; var task1 = new Task(FI.ThreadAdd); var task2 = new Task(FI.ThreadReduce); task1.Start(); task2.Start(); Task.WaitAll(task1, task2); textBox1.Text = textBox1.Text + FI.PersonName +"|"+FI.PersonDeposit.ToString()+Environment.NewLine; } private class FinancialInfo { private string Name=string.Empty; private int Deposit=0; public string PersonName { get { return Name; } set { Name = value; } } public int PersonDeposit { get { return Deposit; } set { Deposit = value; } } public void ThreadChangeFinanceialInfo() { this.Name = this.Name + " | C#"; this.Deposit = this.Deposit + 100; } public void ThreadAdd() { for (int i = 0; i < 1000000; i++) { lock(LockObj) { this.Deposit = this.Deposit + 1; } } } public void ThreadReduce() { for (int i = 0; i < 1000000; i++) { lock(LockObj) { this.Deposit = this.Deposit - 1; } } } } } }
顯示結(jié)果:
上面顯示出了正確的結(jié)果,但是會耗時(shí)。
到此這篇關(guān)于詳解C#中線程傳參,返回值和多線程沖突問題的解決的文章就介紹到這了,更多相關(guān)C#線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#計(jì)算某段代碼的執(zhí)行時(shí)間實(shí)例方法
在本篇文章里我們給大家整理了關(guān)于c#計(jì)算某段代碼的執(zhí)行時(shí)間的方法和經(jīng)驗(yàn),有興趣的朋友們學(xué)習(xí)下。2019-02-02C#中使用Cache框架快速實(shí)現(xiàn)Cache操作
這篇文章介紹了C#中使用Cache框架快速實(shí)現(xiàn)Cache操作的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06基于C#實(shí)現(xiàn)12306的動(dòng)態(tài)驗(yàn)證碼變成靜態(tài)驗(yàn)證碼的方法
這篇文章主要介紹了基于C#實(shí)現(xiàn)12306的動(dòng)態(tài)驗(yàn)證碼變成靜態(tài)驗(yàn)證碼的方法的相關(guān)資料,需要的朋友可以參考下2015-12-12c#解析jobject的數(shù)據(jù)結(jié)構(gòu)
這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07C#使用正則表達(dá)式實(shí)現(xiàn)常見的格式驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了C#如何使用正則表達(dá)式實(shí)現(xiàn)常見的格式驗(yàn)證,例如:電話號碼、密碼、郵編等,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例
這篇文章主要為大家介紹了Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09C#動(dòng)態(tài)調(diào)整數(shù)組大小的方法
這篇文章主要介紹了C#動(dòng)態(tài)調(diào)整數(shù)組大小的方法,涉及C#中靜態(tài)方法CreateInstance的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04