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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章