網站首頁 編程語言 正文
在C#中,開啟一個線程很容易。
Thread Th1= new Thread(func);
Th1.Start();
private void func(object Obj)
{
//處理代碼
}
很多情況下,我們是需要對線程進行傳遞參數的,這個也簡單。
1、線程的單一參數傳遞
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 = $"傳入的參數:{Str}";
}));
}
2、線程的多參數傳遞以及返回值
上面的例子是單一的參數,參數要求是對象,使用的時候進行了拆箱,根據上面的例子對于多參數,可以使用中間對象來處理,就是在中間對象中放置參數和獲取處理后的結果。
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;
}
}
}
顯示結果:
按道理, FI.PersonDeposit的值是123,加了1000000,也減了1000000,那么最終的結果應該還是123,為什么會是這樣呢?
這就是多線程在處理同一對象時所產生的沖突了,產生的就是所謂的“臟數據”。
上面的代碼因為等待線程執行完,進行了休眠,可以使用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;
}
}
}
}
}
}
顯示結果:
上面顯示出了正確的結果,但是會耗時。
原文鏈接:https://blog.csdn.net/dawn0718/article/details/128107337
相關推薦
- 2023-07-08 編寫socket配置文件
- 2022-12-25 python字典中items()函數用法實例_python
- 2023-01-08 Android消息機制原理深入分析_Android
- 2022-09-20 Xmind用例導入到TAPD的解決方案_其它綜合
- 2023-02-01 python多線程、網絡編程、正則表達式詳解_python
- 2022-08-17 R語言學習VennDiagram包繪制韋恩圖示例_R語言
- 2022-10-02 React構建組件的幾種方式及區別_React
- 2022-06-15 golang如何用type-switch判斷interface變量的實際存儲類型_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支