1,async/await
1 /// <summary> 2 /// await/async关键字 3 /// </summary> 4 public class AwaitAsyncShow 5 { 6 public static void TestShow() 7 { 8 Test(); 9 } 10 11 12 private async static Task Test() 13 { 14 Console.WriteLine($"当前主线程id={Thread.CurrentThread.ManagedThreadId}"); 15 { 16 //NoReturnNoAwait(); 17 } 18 { 19 //NoReturn(); 20 //for (int i = 0; i < 10; i++) 21 //{ 22 // Thread.Sleep(300); 23 // Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId} i={i}"); 24 //} 25 } 26 { 27 Task t = NoReturnTask(); 28 Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 29 t.Wait();//主线程等待Task的完成 30 //await t;//await后的代码会由子线程执行 31 } 32 { 33 Task<long> t = SumAsync(); 34 Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 35 long lResult = t.Result;//访问result 主线程等待Task的完成 36 t.Wait();//等价于上一行 37 } 38 { 39 //Task<int> t = SumFactory(); 40 //Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 41 //long lResult = t.Result;//没有await和async 普通的task 42 //t.Wait(); 43 } 44 //Console.WriteLine($"Test Sleep Start {Thread.CurrentThread.ManagedThreadId}"); 45 //Thread.Sleep(10000); 46 //Console.WriteLine($"Test Sleep End {Thread.CurrentThread.ManagedThreadId}"); 47 //Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 48 Console.Read(); 49 } 50 51 52 /// <summary> 53 /// 只有async没有await,会有个warn 54 /// 跟普通方法没有区别 55 /// </summary> 56 private static async void NoReturnNoAwait() 57 { 58 //主线程执行 59 Console.WriteLine($"NoReturnNoAwait Sleep before Task,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 60 Task task = Task.Run(() =>//启动新线程完成任务 61 { 62 Console.WriteLine($"NoReturnNoAwait Sleep before,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 63 Thread.Sleep(3000); 64 Console.WriteLine($"NoReturnNoAwait Sleep after,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 65 }); 66 67 //主线程执行 68 Console.WriteLine($"NoReturnNoAwait Sleep after Task,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 69 } 70 71 /// <summary> 72 /// async/await 73 /// 不能单独await 74 /// await 只能放在task前面 75 /// 不推荐void返回值,使用Task来代替 76 /// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用。Async Void 不行 77 /// </summary> 78 private static async void NoReturn() 79 { 80 //主线程执行 81 Console.WriteLine($"NoReturn Sleep before await,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 82 TaskFactory taskFactory = new TaskFactory(); 83 Task task = taskFactory.StartNew(() => 84 { 85 Console.WriteLine($"NoReturn Sleep before,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 86 Thread.Sleep(3000); 87 Console.WriteLine($"NoReturn Sleep after,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 88 }); 89 await task;//主线程到这里就返回了,执行主线程任务 90 91 //一流水儿的写下去的,耗时任务就用await 92 93 //子线程执行 其实是封装成委托,在task之后成为回调(编译器功能 状态机实现) 94 //task.ContinueWith() 95 //这个回调的线程是不确定的:可能是主线程 可能是子线程 也可能是其他线程 96 Console.WriteLine($"NoReturn Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 97 } 98 99 /// <summary> 100 /// 无返回值 async Task == async void 101 /// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用。Async Void 不行 102 /// </summary> 103 /// <returns></returns> 104 private static async Task NoReturnTask() 105 { 106 //这里还是主线程的id 107 Console.WriteLine($"NoReturnTask Sleep before await,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 108 109 await Task.Run(() => 110 { 111 Console.WriteLine($"NoReturnTask Sleep before,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 112 Thread.Sleep(3000); 113 Console.WriteLine($"NoReturnTask Sleep after,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 114 }); 115 //await task; 116 Console.WriteLine($"NoReturnTask Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}"); 117 118 119 //return new TaskFactory().StartNew(() => { }); //不能return 没有async才行 120 } 121 122 /// <summary> 123 /// 带返回值的Task 124 /// 要使用返回值就一定要等子线程计算完毕 125 /// </summary> 126 /// <returns>async 就只返回long</returns> 127 private static async Task<long> SumAsync() 128 { 129 Console.WriteLine($"SumAsync 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 130 long result = 0; 131 132 await Task.Run(() => 133 { 134 for (int k = 0; k < 10; k++) 135 { 136 Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 137 Thread.Sleep(1000); 138 } 139 140 for (long i = 0; i < 999999999; i++) 141 { 142 result += i; 143 } 144 }); 145 Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 146 return result; 147 } 148 149 /// <summary> 150 /// 真的返回Task 不是async 151 /// 152 /// 要使用返回值就一定要等子线程计算完毕 153 /// </summary> 154 /// <returns>没有async Task</returns> 155 private static Task<int> SumFactory() 156 { 157 Console.WriteLine($"SumFactory 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 158 TaskFactory taskFactory = new TaskFactory(); 159 Task<int> iResult = taskFactory.StartNew<int>(() => 160 { 161 Thread.Sleep(3000); 162 Console.WriteLine($"SumFactory 123 Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 163 return 123; 164 }); 165 //Console.WriteLine($"This is {iResult.Result}"); 166 Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); 167 return iResult; 168 } 169 }
2,多线程实现双色球
方式1
1 /// <summary> 2 /// 多线程双色球项目: 3 /// 双色球:投注号码由6个红色球号码和1个蓝色球号码组成。 4 /// 红色球号码从01--33中选择 5 /// 蓝色球号码从01--16中选择 6 /// </summary> 7 public partial class frmSSQ : Form 8 { 9 public frmSSQ() 10 { 11 InitializeComponent(); 12 13 this.btnStart.Enabled = true; 14 this.btnStop.Enabled = false; 15 } 16 17 #region Data 18 /// <summary> 19 /// 红球集合 20 /// </summary> 21 private string[] RedNums = 22 { 23 "01","02","03","04","05","06","07","08","09","10", 24 "11","12","13","14","15","16","17","18","19","20", 25 "21","22","23","24","25","26","27","28","29","30", 26 "31","32","33" 27 }; 28 29 /// <summary> 30 /// 蓝球集合 31 /// </summary> 32 private string[] BlueNums = 33 { 34 "01","02","03","04","05","06","07","08","09","10", 35 "11","12","13","14","15","16" 36 }; 37 38 39 private static object _Lock = new object(); 40 41 private bool IsGoon = true; 42 #endregion 43 44 #region UI 45 /// <summary> 46 /// 点击开始: 47 /// </summary> 48 /// <param name="sender"></param> 49 /// <param name="e"></param> 50 private void btnStart_Click(object sender, EventArgs e) 51 { 52 try 53 { 54 this.btnStart.Text = "开始ing"; 55 this.btnStart.Enabled = false; 56 this.IsGoon = true; 57 foreach (var item in this.gboSSQ.Controls) 58 { 59 if (item is Label) 60 { 61 ((Label)item).Text = "00"; 62 } 63 } 64 Thread.Sleep(1000); 65 66 TaskFactory taskFactory = new TaskFactory(); 67 List<Task> taskList = new List<Task>(); 68 foreach (var item in this.gboSSQ.Controls) 69 { 70 if (item is Label) 71 { 72 Label lbl = item as Label; 73 taskList.Add(taskFactory.StartNew(() => 74 { 75 while (this.IsGoon) 76 { 77 string text = ""; 78 if (lbl.Name.Contains("Red")) 79 { 80 //1 解决冲突的最好办法,是没有冲突,上来就随机分6组,每个线程只取一个组的 81 //2 线程安全的集合,出一个进一个 82 //3 每次先找出6个不同的球,然后分配给线程 83 //4 每次线程随意获取球,更新前检测下有没有冲突,有则重新随机,没有则更新 84 text = this.GetRandomText(); 85 lock (_Lock) 86 { 87 List<string> redList = this.GetUsedRed(lbl); 88 if (redList.Contains(text)) 89 continue; 90 else 91 { 92 Thread.Sleep(50);//让停止的时候,线程可能在这里 93 this.UpdateLable(lbl, text); 94 } 95 } 96 } 97 else 98 { 99 int index = RandomHelper.GetRandomNumber(0, 16); 100 //Random random = new Random();//伪随机 101 //string text = this.BlueNums[random.Next(0, 15)]; 102 //int index = RandomHelper.GetRandomNumber(0, 16); 103 text = this.BlueNums[index]; 104 //lbl.Text = text;//不行 105 this.UpdateLable(lbl, text); 106 } 107 108 //this.UpdateLable(lbl, text); 109 Thread.Sleep(50); 110 } 111 })); 112 } 113 } 114 taskFactory.ContinueWhenAll(taskList.ToArray(), tList => this.ShowResult()); 115 116 117 this.btnStop.Enabled = true;//正确的时机打开:所有的求都不是0再true 118 } 119 catch (Exception ex) 120 { 121 Console.WriteLine("双色球启动出现异常:{0}", ex.Message); 122 } 123 } 124 125 /// <summary> 126 /// 点击结束 127 /// </summary> 128 /// <param name="sender"></param> 129 /// <param name="e"></param> 130 private void btnStop_Click(object sender, EventArgs e) 131 { 132 this.btnStart.Enabled = true; 133 this.btnStop.Enabled = false; 134 this.IsGoon = false; 135 //this.ShowResult(); 136 } 137 138 /// <summary> 139 /// 弹框提示数据 140 /// </summary> 141 private void ShowResult() 142 { 143 MessageBox.Show(string.Format("本期双色球结果为:{0} {1} {2} {3} {4} {5} 蓝球{6}" 144 , this.lblRed1.Text 145 , this.lblRed2.Text 146 , this.lblRed3.Text 147 , this.lblRed4.Text 148 , this.lblRed5.Text 149 , this.lblRed6.Text 150 , this.lblBlue.Text)); 151 } 152 #endregion 153 154 #region PrivateMethod 155 private void UpdateLable(Label label, string text) 156 { 157 this.Invoke(new Action(() => 158 { 159 label.Text = text; 160 })); 161 } 162 163 private string GetRandomText() 164 { 165 int index = RandomHelper.GetRandomNumber(0, 33); 166 return this.RedNums[index]; 167 } 168 169 private List<string> GetUsedRed(Label lbl) 170 { 171 List<string> usedList = new List<string>(); 172 foreach (var labItem in this.gboSSQ.Controls) 173 { 174 if (labItem is Label && labItem != lbl)//当前的数字可以用 175 { 176 usedList.Add(((Label)labItem).Text); 177 } 178 } 179 return usedList; 180 } 181 182 #endregion 183 }
方式2
1 /// <summary> 2 /// 双色球:投注号码由6个红色球号码和1个蓝色球号码组成。 3 /// 红色球号码从01--33中选择 4 /// 蓝色球号码从01--16中选择 5 /// </summary> 6 public partial class Form1 : Form 7 { 8 public Form1() 9 { 10 InitializeComponent(); 11 this.btnStop.Enabled = false; 12 } 13 14 #region 15 /// <summary> 16 /// 红球集合 17 /// </summary> 18 private string[] RedNums = 19 { 20 "01","02","03","04","05","06","07","08","09","10", 21 "11","12","13","14","15","16","17","18","19","20", 22 "21","22","23","24","25","26","27","28","29","30", 23 "31","32","33" 24 }; 25 26 /// <summary> 27 /// 蓝球集合 28 /// </summary> 29 private string[] BlueNums = 30 { 31 "01","02","03","04","05","06","07","08","09","10", 32 "11","12","13","14","15","16" 33 }; 34 private bool isGoon = true; 35 #endregion 36 37 /// <summary> 38 /// 开始 39 /// </summary> 40 /// <param name="sender"></param> 41 /// <param name="e"></param> 42 private void btnStart_Click(object sender, EventArgs e) 43 { 44 try 45 { 46 this.btnStart.Text = "开始ing"; 47 this.btnStart.Enabled = false; 48 this.isGoon = true; 49 this.lblBlue.Text = "00"; 50 this.lblRed1.Text = "00"; 51 this.lblRed2.Text = "00"; 52 this.lblRed3.Text = "00"; 53 this.lblRed4.Text = "00"; 54 this.lblRed5.Text = "00"; 55 this.lblRed6.Text = "00"; 56 Thread.Sleep(1000); 57 this.btnStop.Enabled = true;//合适打开 58 59 List<Task> taskList = new List<Task>(); 60 TaskFactory taskFactory = new TaskFactory(); 61 foreach (Control c in this.gboSSQ.Controls) 62 { 63 if (c is Label) 64 { 65 Label lbl = (Label)c; 66 taskList.Add(taskFactory.StartNew(() => 67 { 68 while (isGoon) 69 { 70 string text = this.GetNum(lbl);//获取num 71 this.UpdateLbl(lbl, text);//更新界面 72 } 73 //Console.WriteLine("线程完成"); 74 })); 75 } 76 } 77 78 taskFactory.ContinueWhenAll(taskList.ToArray(), t => 79 { 80 MessageShow(); 81 }); 82 } 83 catch (Exception ex) 84 { 85 Console.WriteLine("双色球出现异常:{0}", ex.Message); 86 } 87 } 88 89 /// <summary> 90 /// 结束 91 /// </summary> 92 /// <param name="sender"></param> 93 /// <param name="e"></param> 94 private void btnStop_Click(object sender, EventArgs e) 95 { 96 this.btnStop.Enabled = false; 97 this.btnStart.Enabled = true; 98 btnStart.Text = "开始"; 99 this.isGoon = false; 100 101 } 102 103 /// <summary> 104 /// 打印结果 105 /// </summary> 106 private void MessageShow() 107 { 108 MessageBox.Show(string.Format("本期双色球结果是 {0} {1} {2} {3} {4} {5} {6}", 109 lblRed1.Text, lblRed2.Text, lblRed3.Text, lblRed4.Text, lblRed5.Text, lblRed6.Text, lblBlue.Text)); 110 } 111 112 private static object GetNum_Lock = new object(); 113 114 /// <summary> 115 /// 获取num 116 /// </summary> 117 /// <param name="label"></param> 118 /// <returns></returns> 119 private string GetNum(Label label) 120 { 121 Thread.Sleep(1000);//让电脑轻松一点,可以随意切换线程 122 if (label.Name.Equals("lblBlue")) 123 { 124 return this.BlueNums[new Random().Next(0, this.BlueNums.Length - 1)];//0到15 125 } 126 else 127 { 128 //33选6 129 string text = this.RedNums[new Random().Next(0, this.RedNums.Length - 1)];//0到32 130 lock (GetNum_Lock) 131 { 132 List<string> usedNumList = this.GetUsedNums(); 133 while (usedNumList.Contains(text)) 134 { 135 text = this.RedNums[new Random().Next(0, this.RedNums.Length - 1)];//0到32 136 } 137 return text; 138 } 139 140 } 141 } 142 143 /// <summary> 144 /// 获取当前界面上的球号码 145 /// </summary> 146 /// <returns></returns> 147 private List<string> GetUsedNums() 148 { 149 List<string> usedNumList = new List<string>(); 150 foreach (Control c in this.gboSSQ.Controls) 151 { 152 if (c is Label && ((Label)c).Name.Contains("Red")) 153 { 154 usedNumList.Add(((Label)c).Text); 155 } 156 } 157 return usedNumList; 158 } 159 160 /// <summary> 161 /// 更新界面 162 /// </summary> 163 /// <param name="lbl"></param> 164 /// <param name="text"></param> 165 private void UpdateLbl(Label lbl, string text) 166 { 167 if (lbl.InvokeRequired) 168 { 169 this.Invoke(new Action(() => lbl.Text = text));//交给UI线程去更新 170 } 171 else 172 { 173 lbl.Text = text; 174 } 175 } 176 177 }