首页 新闻 会员 周边

希望高手三言两语给予启示,给段代码得以解惑。

0
悬赏园豆:5 [已解决问题] 解决于 2015-06-16 11:12

用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);
            Task t1 = new Task(() => { CallWithAsync(tc); });
            t1.ContinueWith(t => { Console.WriteLine("Tickets has been sold out. Press any key to quit:"); });
            t1.Start();
            Console.ReadLine();
        }
        //调用异步方法
        private static void CallWithAsync(Ticket tc) 
        {
            Task.Run(() =>
            {
                Task.Run(() => { SellTicket("Window1", tc); });
                Task.Run(() => { SellTicket("Window2", tc); });
                Task.Run(() => { SellTicket("Window3", tc); });
                Task.Run(() => { SellTicket("Window4", tc); });
            });
        }
        //卖票方法
        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;
        }
    }
}

运行结果:

应该怎么办呢?我明明用了ContinueWith方法了,但是没有效果。

另:如果有更好的思路请给段代码学习学习。 :)

C#
天外归云的主页 天外归云 | 菜鸟二级 | 园豆:368
提问于:2015-06-16 09:41
< >
分享
最佳答案
1

因为这里的 Task 一闪而过,不会像你认为的会等到四个 Task 完成后才返回。

Task.Run(() =>
            {
                Task.Run(() => { SellTicket("Window1", tc); });
                Task.Run(() => { SellTicket("Window2", tc); });
                Task.Run(() => { SellTicket("Window3", tc); });
                Task.Run(() => { SellTicket("Window4", tc); });
            });

收获园豆:5
Launcher | 高人七级 |园豆:45045 | 2015-06-16 09:50

我把这个方法调用放在一个task里,然后task.ContinueWith不是应该在这个task执行完毕之后才执行ContinueWith中的内容吗?

天外归云 | 园豆:368 (菜鸟二级) | 2015-06-16 09:56

应该怎么修改呢?

天外归云 | 园豆:368 (菜鸟二级) | 2015-06-16 09:56

@天外归云: 你的 t1 是在 t1 执行完 CallWithAsync 后才执行 ContinueWith 中的内容的。

Launcher | 园豆:45045 (高人七级) | 2015-06-16 10:54

@天外归云: 

List<Task> tasks = new List<Task>();

 

for(int i=0;i<4;i++)

   tasks.Add(Task.Run(() => { SellTicket(string.Format("Window{0}",i), tc); }));

 

Task.WaitAll(tasks.ToArray());

Launcher | 园豆:45045 (高人七级) | 2015-06-16 11:00

@Launcher: 非常感谢!已经改好了!

天外归云 | 园豆:368 (菜鸟二级) | 2015-06-16 11:10

@Launcher: 

//入口
static void Main(string[] args)
{
Ticket tc = new Ticket(10);
CallWithAsync(tc);
Console.WriteLine("Tickets has been sold out. Press any key to quit:");
Console.ReadLine();
}
//调用异步方法
private static void CallWithAsync(Ticket tc)
{
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() => { SellTicket("Window1", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window2", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window3", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window4", tc); }));
Task.WaitAll(tasks.ToArray());
}

天外归云 | 园豆:368 (菜鸟二级) | 2015-06-16 11:11
其他回答(2)
0

Task.WaitAll(task);

task.start();

羽商宫 | 园豆:2490 (老鸟四级) | 2015-06-16 10:19

已经改好啦:

//入口
static void Main(string[] args)
{
Ticket tc = new Ticket(10);
CallWithAsync(tc);
Console.WriteLine("Tickets has been sold out. Press any key to quit:");
Console.ReadLine();
}
//调用异步方法
private static void CallWithAsync(Ticket tc)
{
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() => { SellTicket("Window1", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window2", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window3", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window4", tc); }));
Task.WaitAll(tasks.ToArray());
}

支持(0) 反对(0) 天外归云 | 园豆:368 (菜鸟二级) | 2015-06-16 11:11
0

这种就是典型的你在逗我l。。

你自己都知道外面的异步任务要等待才行,为什么里面的异步的任务就不用等待?

吴瑞祥 | 园豆:29449 (高人七级) | 2015-06-16 10:25

改好啦:

//入口
static void Main(string[] args)
{
Ticket tc = new Ticket(10);
CallWithAsync(tc);
Console.WriteLine("Tickets has been sold out. Press any key to quit:");
Console.ReadLine();
}
//调用异步方法
private static void CallWithAsync(Ticket tc)
{
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() => { SellTicket("Window1", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window2", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window3", tc); }));
tasks.Add(Task.Run(() => { SellTicket("Window4", tc); }));
Task.WaitAll(tasks.ToArray());
}

支持(0) 反对(0) 天外归云 | 园豆:368 (菜鸟二级) | 2015-06-16 11:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册