若是死循環獨佔線程,500個死循環要佔用500個線程,若是死循環不獨佔線程,500個死循環,用200個線程也行,用20個線程也行,無非是執行的慢點異步
這樣能夠把同步操做改寫爲異步,而且節省線程佔用async
問個問題:寫個Socket服務端,接收數據不許用BeginReceive和ReceiveAsync,只能用Receive,Socket客戶端10000個,線程池最大不許超過1000,如何實現?ide
網上是用Select模型,要維護一個Socket對象列表,若是用下面的代碼,能夠不用維護Socket對象列表,直接有多少Socket對象,就寫多少while(true)測試
代碼:spa
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是否能響應事件 }); } } }