詳解C#中線程傳參,返回值和多線程沖突問題的解決
在C#中,開啟一個線程很容易。
Thread Th1= new Thread(func); Th1.Start(); private void func(object Obj) { //處理代碼 }
很多情況下,我們是需要對線程進行傳遞參數(shù)的,這個也簡單。
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ù)要求是對象,使用的時候進行了拆箱,根據(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、多線程可能引起的沖突
多線程在處理同一對象時容易引起潛在的沖突,這個顯而易見,例如:
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é)果應該還是123,為什么會是這樣呢?
這就是多線程在處理同一對象時所產(chǎn)生的沖突了,產(chǎn)生的就是所謂的“臟數(shù)據(jù)”。
上面的代碼因為等待線程執(zhí)行完,進行了休眠,可以使用Task來寫更簡單。
var task1 = new Task(FI.ThreadAdd); var task2 = new Task(FI.ThreadReduce); task1.Start(); task2.Start(); Task.WaitAll(task1,task2);
Task是比Thread更加高級的概念,一個Task至少包含一個Thread。
解決上面的沖突就是對可能引起沖突的對象進行加鎖判斷。
完整代碼:
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é)果,但是會耗時。
到此這篇關于詳解C#中線程傳參,返回值和多線程沖突問題的解決的文章就介紹到這了,更多相關C#線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
基于C#實現(xiàn)12306的動態(tài)驗證碼變成靜態(tài)驗證碼的方法
這篇文章主要介紹了基于C#實現(xiàn)12306的動態(tài)驗證碼變成靜態(tài)驗證碼的方法的相關資料,需要的朋友可以參考下2015-12-12c#解析jobject的數(shù)據(jù)結(jié)構(gòu)
這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例
這篇文章主要為大家介紹了Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09