詳解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,為什么會(huì)是這樣呢?
這就是多線程在處理同一對象時(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é)果,但是會(huì)耗時(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-02
C#中使用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-12
c#解析jobject的數(shù)據(jù)結(jié)構(gòu)
這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
C#使用正則表達(dá)式實(shí)現(xiàn)常見的格式驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了C#如何使用正則表達(dá)式實(shí)現(xiàn)常見的格式驗(yàn)證,例如:電話號(hào)碼、密碼、郵編等,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例
這篇文章主要為大家介紹了Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
C#動(dòng)態(tài)調(diào)整數(shù)組大小的方法
這篇文章主要介紹了C#動(dòng)態(tài)調(diào)整數(shù)組大小的方法,涉及C#中靜態(tài)方法CreateInstance的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04

