詳解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ù)要求是對象,使用的時候進(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、多線程可能引起的沖突
多線程在處理同一對象時容易引起潛在的沖突,這個顯而易見,例如:
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,為什么會是這樣呢?
這就是多線程在處理同一對象時所產(chǎn)生的沖突了,產(chǎn)生的就是所謂的“臟數(shù)據(jù)”。
上面的代碼因為等待線程執(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é)果,但是會耗時。
到此這篇關(guān)于詳解C#中線程傳參,返回值和多線程沖突問題的解決的文章就介紹到這了,更多相關(guān)C#線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于C#實現(xiàn)12306的動態(tài)驗證碼變成靜態(tài)驗證碼的方法
這篇文章主要介紹了基于C#實現(xiàn)12306的動態(tài)驗證碼變成靜態(tài)驗證碼的方法的相關(guān)資料,需要的朋友可以參考下2015-12-12
c#解析jobject的數(shù)據(jù)結(jié)構(gòu)
這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例
這篇文章主要為大家介紹了Unity性能優(yōu)化Shader函數(shù)ShaderUtil.GetShaderGlobalKeywords用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09

