題目:模擬窗口賣票,四個窗口同時對外開放售票,需要按順序售出。
要求:輸出每一張票的售出時間和售出窗口,不能出現票未售出或者被售出多次的情況。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.IO; using System.Reflection; using System.Diagnostics; namespace SellTicketsSynchronously { class Program { //入口 static void Main(string[] args) { Ticket tc = new Ticket(10); Thread sellWindowA = new Thread(new ParameterizedThreadStart(SellTicket)); Thread sellWindowB = new Thread(new ParameterizedThreadStart(SellTicket)); Thread sellWindowC = new Thread(new ParameterizedThreadStart(SellTicket)); Thread sellWindowD = new Thread(new ParameterizedThreadStart(SellTicket)); sellWindowA.Name = "Window A"; sellWindowB.Name = "Window B"; sellWindowC.Name = "Window C"; sellWindowD.Name = "Window D"; sellWindowA.Start(tc); sellWindowB.Start(tc); sellWindowC.Start(tc); sellWindowD.Start(tc); sellWindowA.Join(); sellWindowB.Join(); sellWindowC.Join(); sellWindowD.Join(); Console.WriteLine("Tickets has been sold out. Press any key to quit:"); Console.ReadLine(); } //賣票方法 public static void SellTicket(object obj) { Ticket ticket = obj as Ticket; while (ticket.NumOfTickets>0) { lock (ticket) { if (ticket.NumOfTickets > 0) { try { ticket.NumOfTickets--; Console.WriteLine( DateTime.Now.ToString()+":"+Thread.CurrentThread.Name + " sells a ticket, " + ticket.NumOfTickets + " tickets left."); } catch (Exception ex) { WriteLog(ex); } } } Random random = new Random(); Thread.Sleep(random.Next(100,500)); } } //打log方法 private static void WriteLog(Exception ex) { string logUrl = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\SellTicketslog.txt"; if (File.Exists(@logUrl)) { using (FileStream fs = new FileStream(logUrl, FileMode.Append)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } else { using (FileStream fs = new FileStream(logUrl, FileMode.CreateNew)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } } } //票類 class Ticket { public int NumOfTickets { get; set; } public Ticket(int num) { this.NumOfTickets = num; } } }
運行結果:
不知道這么寫會不會有問題,求指點。
————————修改版——————————
經過園友指點,我改用了Task寫了這段代碼,其間得到了園友的幫助,非常感謝!
修改后的代碼如下(藍色字體為修改的部分):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.IO; using System.Reflection; using System.Diagnostics; namespace SellTicketsSynchronously { class Program { //入口 static void Main(string[] args) { Ticket tc = new Ticket(10); WaitForAllSales(tc); Console.WriteLine("Tickets has been sold out. Press any key to quit:"); Console.ReadLine(); } //售罄方法 private static void WaitForAllSales(Ticket tc) { //創建一個Task類型的泛型list List<Task> tasks = new List<Task>(); for (int i = 1; i <= 4; i++) { //將所有的售票task存入list tasks.Add(Task.Run(() => { SellTicket(string.Format("Window"+i), tc); })); } //等待所有的task都完成 Task.WaitAll(tasks.ToArray()); } //賣票方法 public static void SellTicket(string windowName, object obj) { string nameOfWindow = windowName; Ticket ticket = obj as Ticket; while (ticket.NumOfTickets > 0) { lock (ticket) { if (ticket.NumOfTickets > 0) { try { ticket.NumOfTickets--; Console.WriteLine(DateTime.Now.ToString() + ":" + nameOfWindow + " sells a ticket, " + ticket.NumOfTickets + " tickets left."); } catch (Exception ex) { WriteLog(ex); } } } Random random = new Random(); Thread.Sleep(random.Next(100,500)); } } //打log方法 private static void WriteLog(Exception ex) { string logUrl = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\SellTicketslog.txt"; if (File.Exists(@logUrl)) { using (FileStream fs = new FileStream(logUrl, FileMode.Append)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } else { using (FileStream fs = new FileStream(logUrl, FileMode.CreateNew)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } } } //票類 class Ticket { public int NumOfTickets { get; set; } public Ticket(int num) { this.NumOfTickets = num; } } }
運行結果:
歡迎大家發散思維,繼續提出寶貴意見!:)
------------------------------------------------------------------------------------------------------------
經過一位朋友細心的發現,上面這個程序邏輯是有問題的,一直都是售票窗口5在售票,修改后的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.IO; using System.Reflection; using System.Diagnostics; namespace SellTicketsSynchronously { class Program { //入口 static void Main(string[] args) { Ticket tc = new Ticket(20); WaitForAllSales(tc); Console.ReadLine(); } //售罄方法 private static void WaitForAllSales(Ticket tc) { //創建一個Task類型的泛型list List<Task> tasks = new List<Task>(); System.Random ran = new Random(); while (tc.NumOfTickets > 0) { int i = ran.Next(1,6); //將所有的售票task存入list tasks.Add(Task.Run(() => { SellTicket(string.Format("Window" + i), tc); })); Task.WaitAll(tasks.ToArray()); } Console.WriteLine("Tickets has been sold out. Press any key to quit:"); } //賣票方法 public static void SellTicket(string windowName, object obj) { string nameOfWindow = windowName; Ticket ticket = obj as Ticket; lock (ticket) { if (ticket.NumOfTickets > 0) { try { ticket.NumOfTickets--; Console.WriteLine(DateTime.Now.ToString() + ":" + nameOfWindow + " sells a ticket, " + ticket.NumOfTickets + " tickets left."); } catch (Exception ex) { WriteLog(ex); } } Random random = new Random(); Thread.Sleep(random.Next(100,500)); } } //打log方法 private static void WriteLog(Exception ex) { string logUrl = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\SellTicketslog.txt"; if (File.Exists(@logUrl)) { using (FileStream fs = new FileStream(logUrl, FileMode.Append)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } else { using (FileStream fs = new FileStream(logUrl, FileMode.CreateNew)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } } } //票類 class Ticket { public int NumOfTickets { get; set; } public Ticket(int num) { this.NumOfTickets = num; } } }
本次修改了售罄方法和入口方法(橙色字體),運行結果如下:
歡迎繼續提出意見!謝謝大家~