如果死回圈獨占執行緒,500個死回圈要占用500個執行緒,如果死回圈不獨占執行緒,500個死回圈,用200個執行緒也行,用20個執行緒也行,無非是執行的慢點
這樣可以把同步操作改寫為異步,并且節省執行緒占用
問個問題:寫個Socket服務端,接收資料不準用BeginReceive和ReceiveAsync,只能用Receive,Socket客戶端10000個,執行緒池最大不準超過1000,如何實作?
網上是用Select模型,要維護一個Socket物件串列,如果用下面的代碼,可以不用維護Socket物件串列,直接有多少Socket物件,就寫多少while(true)
代碼:
using System; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Utils; /** * 如何寫個死回圈,既不獨占執行緒,又不阻塞UI執行緒 */ namespace test { public partial class Form1 : Form { private int _n = 0; private bool _run1 = false; private bool _run2 = false; private TaskSchedulerEx _task1 = new TaskSchedulerEx(2, 2); //只給2個執行緒 public Form1() { InitializeComponent(); ThreadPool.SetMaxThreads(12, 12); //最多給12個執行緒 ThreadPool.SetMinThreads(10, 10); } private void Form1_Load(object sender, EventArgs e) { } /// <summary> /// 測驗1 /// 現象:會輸出i=5,也會輸出i=15,button3有事件回應,因為20個死回圈,2個執行緒也能處理,只不過處理速度慢,加大執行緒池容量可加快處理速度 /// </summary> private void button1_Click(object sender, EventArgs e) { _n = 0; button1.Enabled = false; button2.Enabled = true; _run1 = true; _run2 = false; textBox1.Text = string.Empty; for (int i = 1; i <= 20; i++) //啟動20個死回圈 { _task1.Run(async (obj) => //用_task1(只給2個執行緒)啟動20個死回圈 { dynamic var = (dynamic)obj; while (_run1) //此while不會獨占執行緒 { Task t = Task.Factory.StartNew(() => { Thread.Sleep(100); Interlocked.Increment(ref _n); if (var.i == 5 || var.i == 15) { int a1; int a2; int m1; int m2; ThreadPool.GetMaxThreads(out m1, out a1); ThreadPool.GetAvailableThreads(out m2, out a2); Log("當前使用輔助執行緒數:" + (m1 - m2) + ",當前使用異步執行緒數:" + (a1 - a2) + ",i=" + var.i + ",n=" + _n); } }); await t; } }, new { i = i }); } } /// <summary> /// 測驗2 /// 現象:只輸出i=5,不輸出i=15,button3不能回應事件,因為有20個死回圈,12個執行緒不夠用,但因為12個執行緒比較多,所以處理速度較快 /// </summary> private void button2_Click(object sender, EventArgs e) { _n = 0; button1.Enabled = true; button2.Enabled = false; _run1 = false; _run2 = true; textBox1.Text = string.Empty; for (int i = 1; i <= 20; i++) //啟動20個死回圈 { Task.Factory.StartNew((obj) => //用Task(最多12個執行緒)啟動20個死回圈 { dynamic var = (dynamic)obj; while (_run2) //此while會獨占一個執行緒 { Thread.Sleep(100); Interlocked.Increment(ref _n); if (var.i == 5 || var.i == 15) { int a1; int a2; int m1; int m2; ThreadPool.GetMaxThreads(out m1, out a1); ThreadPool.GetAvailableThreads(out m2, out a2); Log("當前使用輔助執行緒數:" + (m1 - m2) + ",當前使用異步執行緒數:" + (a1 - a2) + ",i=" + var.i + ",n=" + _n); } } }, new { i = i }); } } private void button3_Click(object sender, EventArgs e) { Task.Factory.StartNew(() => { Log("button3_Click 有回應"); //測驗button3是否能回應事件 }); } } }View Code
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/17071.html
標籤:C#
