如果死迴圈獨占線程,500個死迴圈要占用500個線程,如果死迴圈不獨占線程,500個死迴圈,用200個線程也行,用20個線程也行,無非是執行的慢點 這樣可以把同步操作改寫為非同步,並且節省線程占用 問個問題:寫個Socket服務端,接收數據不准用BeginReceive和ReceiveAsync,只能 ...
如果死迴圈獨占線程,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