async/await,多线程实现双色球

  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     }
View Code

  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     }
View Code

  方式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     }
View Code

原文地址:https://www.cnblogs.com/shangec/p/9821927.html