詳解C#中線程傳參,返回值和多線程沖突問題的解決
在C#中,開啟一個線程很容易。
Thread Th1= new Thread(func);
Th1.Start();
private void func(object Obj)
{
//處理代碼
}
很多情況下,我們是需要對線程進(jìn)行傳遞參數(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ù)要求是對象,使用的時(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í)容易引起潛在的沖突,這個顯而易見,例如:
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更加高級的概念,一個Task至少包含一個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# 如何實(shí)現(xiàn)一個帶通知的List<T>
這篇文章主要介紹了C# 如何實(shí)現(xiàn)一個帶通知的List<T>,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-02-02
Unity Shader相交算法實(shí)現(xiàn)簡易防能量盾
這篇文章主要為大家詳細(xì)介紹了Unity Shader相交算法實(shí)現(xiàn)簡易防能量盾,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
C#實(shí)現(xiàn)啟用與禁用本地網(wǎng)絡(luò)的方式小結(jié)【3種方式】
這篇文章主要介紹了C#實(shí)現(xiàn)啟用與禁用本地網(wǎng)絡(luò)的方式,結(jié)合實(shí)例形式總結(jié)分析了使用Hnetcfg.dll、Shell32.dll及setupapi.dll三種啟用與禁用本地網(wǎng)絡(luò)的操作方法,需要的朋友可以參考下2016-07-07
C# 批量生成隨機(jī)密碼必須包含數(shù)字和字母并用加密算法加密
這篇文章主要介紹了C# 批量生成隨機(jī)密碼必須包含數(shù)字和字母并用加密算法加密,需要的朋友參考下2017-01-01
WPF數(shù)據(jù)綁定時(shí)出現(xiàn)StringFormat失效的原因和解決方法
在數(shù)據(jù)綁定過程中,我們經(jīng)常會使用StringFormat對要顯示的數(shù)據(jù)進(jìn)行格式化,以便獲得更為直觀的展示效果,但在某些情況下格式化操作并未生效,所以本文介紹了WPF數(shù)據(jù)綁定時(shí)出現(xiàn)StringFormat失效的原因和解決方法,需要的朋友可以參考下2024-12-12

