首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C#异步方法调用一直到Main

C#异步方法调用一直到Main
EN

Stack Overflow用户
提问于 2015-05-26 17:26:19
回答 5查看 8.1K关注 0票数 5

有人能澄清一下这个例子吗?当然,这个例子不起作用:

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)//main cant' be async
    {
        int res = test();//I must put await here

        Console.WriteLine("END");
    }

    public async static Task<int> test()
    { //why can't I make it just: public int test()??
        int a1, a2, a3, a4;

        a1 = await GetNumber1();
        a2 = await GetNumber2();
        a3 = await GetNumber3();

        a4 = a1 + a2 + a3;
        return a4;
    }

    public static async Task<int> GetNumber1()
    {
        await Task.Run(() =>
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("GetNumber1");
                    System.Threading.Thread.Sleep(100);
                }
            });
        return 1;
    }

我正在尝试使用"await“从GenNumberX方法中”收集“值。我想以某种方式使方法“测试”而不是异步。我不明白为什么当我使用await来获取一个值时,测试必须是异步的。这个示例让我在使用异步的每个方法上编写异步,当我向上钻取到Main时,我不能使它异步?

如何编写真实世界的示例:

代码语言:javascript
复制
public bool ReserveAHolliday()
{
        bool hotelOK = await ReserveAHotel();//HTTP async request
        bool flightOK = await ReserveFlight();////HTTP async request
        bool result = hotelOK && flightOK;
        return result;
}

如何使方法ReserveAHolliday同步?我是不是遗漏了什么或者不理解异步等待机制的用法?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-05-26 18:38:49

下面是一个完整的例子。您可以从ReserverAHoliday (取决于您注释的行)同步(bool r= ReserveAHolliday().Result;)和异步(只需调用ReserveAHolliday();)运行MAIN。您可以看到效果(在预订完成之前/之后打印“END”)。我更喜欢await Task.WhenAll()方法,它更具可读性。还要注意的是,在GetNumber1中使用await Task.Delay(100)而不是Thread.sleep。

代码语言:javascript
复制
    class Program
{
    static void Main(string[] args)//main cant' be async
    {
        //int res = test().Result;//I must put await here
        bool r = ReserveAHolliday().Result; //this will run Synchronously.
        //ReserveAHolliday(); //this option will run aync : you will see "END" printed before the reservation is complete.
        Console.WriteLine("END");
        Console.ReadLine();
    }

    public async static Task<int> test()
    { //why can't I make it just: public int test()??
        //becuase you cannot use await in synchronous methods. 
        int a1, a2, a3, a4;

        a1 = await GetNumber1();
        a2 = await GetNumber1();
        a3 = await GetNumber1();

        a4 = a1 + a2 + a3;
        return a4;
    }

    public static async Task<int> GetNumber1()
    {
        //await Task.Run(() =>
        //    {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("GetNumber1");
                    await Task.Delay(100); // from what I read using Task.Delay is preferred to using  System.Threading.Thread.Sleep(100);
                }
        //    });
        return 1;
    }

    public async static Task<bool> ReserveAHolliday()
    {
        //bool hotelOK = await ReserveAHotel();//HTTP async request
        //bool flightOK = await ReserveAHotel();////HTTP async request
        var t1 = ReserveAHotel("FirstHotel");
        var t2 = ReserveAHotel("SecondHotel");
        await Task.WhenAll(t1, t2);
        bool result = t1.Result && t1.Result;// hotelOK && flightOK;
        return result;
    }
    public static async Task<bool> ReserveAHotel(string name)
    {
        Console.WriteLine("Reserve A Hotel started for "+ name);
        await Task.Delay(3000);
        if (name == "FirstHotel") 
            await Task.Delay(500); //delaying first hotel on purpose.
        Console.WriteLine("Reserve A Hotel done for " + name);
        return true;
    }
}
票数 2
EN

Stack Overflow用户

发布于 2015-05-26 17:35:57

异步需要从某个地方开始,因为您的程序有一个起始点,所以在这一点上它是一个同步方法。大多数async都是从我们所说的async void开始的,基本上就是触发和忘记方法。它启动一个任务,并不关心它返回什么。如果你需要等待同步方法中的某些东西,你可以在任务上使用.Wait()方法,或者使用.Result来获得任务的结果。

对于您的真实示例,如果您希望同时运行这两个任务,则需要执行以下操作:

代码语言:javascript
复制
public async Task<bool> ReserveAHoliday()
{
        //Initialize and start this task
        Task<bool> hotelTask = ReserveAHotel();//HTTP async request
        //Initialize and start this task
        Task<bool> flightTask = ReserveFlight();////HTTP async request
        //Await until hotel task is done, and get the bool
        bool hotelOK = await hotelTask;
        //Await until flight task is done (This might have already finished while the hotel was grabbing, and get the bool
        bool flightOK = await flightTask;
        bool result = hotelOK && flightOK;
        //Return the final result
        return result;
}

我强烈推荐看this video。它很好地介绍了异步是如何工作的,并且可以让你快速进入异步的奇妙世界。

票数 0
EN

Stack Overflow用户

发布于 2015-05-26 17:46:34

感谢FrankerZ给出的正确答案!所以我的小例子应该是这样的:

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        var task = test();
        task.Wait(); //this stops async behaviour
        int result = task.Result;// get return value form method "test"
        Console.WriteLine("RESULT IS = " + result);
    }

    public async static Task<int> test()
    {
        int a1, a2, a3, a4;

        //run all tasks
        //all tasks are doing their job "at the same time"
        var taskA1 = GetNumber1();
        var taskA2 = GetNumber2();
        var taskA3 = GetNumber3();

        //wait for task results
        //here I am collecting results from all tasks
        a1 = await taskA1;
        a2 = await taskA2;
        a3 = await taskA3;

        //get value from all task results
        a4 = a1 + a2 + a3;
        return a4;
    }

    public static async Task<int> GetNumber1()
    {
        await Task.Run(() =>
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("GetNumber1");
                    System.Threading.Thread.Sleep(100);
                }
            });
        return 1;
    }

//省略其他方法,因为它们与GetNumber1相同}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30454613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档