Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步和等待不起作用_C#_.net_Asynchronous_Async Await - Fatal编程技术网

C# 异步和等待不起作用

C# 异步和等待不起作用,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,我正在尝试学习.NET4.5的异步和等待特性 static async void Method() { await Task.Run(new Action(DoSomeProcess)); Console.WriteLine("All Methods have been executed"); } static void DoSomeProcess() { System.Threading.Thread.S

我正在尝试学习.NET4.5的异步和等待特性

    static async void Method()
    {
        await Task.Run(new Action(DoSomeProcess));
        Console.WriteLine("All Methods have been executed");
    }

    static void DoSomeProcess()
    {
        System.Threading.Thread.Sleep(3000);
    }

    static void Main(string[] args)
    {
        Method();
        //Console.WriteLine("Method Started");
        Console.ReadKey();
    }
这段代码不会在控制台上给我任何结果。我不明白为什么。我的意思是任务不应该是没有阻塞的线程。但是,如果我在main方法中取消对Console.WriteLine()的注释,一切似乎都正常


有人能告诉我这里发生了什么吗?

对于异步/等待模式,一些事情与之前的线程不同

  • 您不应该使用
    System.Threading.Thread.Sleep
    因为这仍然是阻塞,不能与异步一起工作。 改为使用
    Task.Delay

  • 考虑使所有代码异步。控制台中只有Main方法不能异步

  • 避免
    异步void
    方法。基本上,async void只适用于无法返回某些内容的事件处理程序。所有其他异步方法应返回
    Task
    Task

  • 修改您的示例:

        static async Task Method()
        {
            await DoSomeProcess();
            Console.WriteLine("All Methods have been executed");
        }
    
        static async Task DoSomeProcess()
        {
            await Task.Delay(3000);
        }
    
    现在改变你的主要方法,因为这应该是你开始任务的地方

        Task.Run(() => Method()).Wait();
        //Console.WriteLine("Method Started");
        Console.ReadKey();
    

    学习如何正确使用
    async
    wait
    关键字有一个很小的学习曲线

    问题是没有人在等待谁,还有一些其他细节,如
    SyncronizationContext
    任务

    你应该查看一些文章:

    要在Console中使用async和await关键字,您需要额外的代码: 或 或

    我通常采用这种方法:

    static void Main(string[] args)
    {
        Console.WriteLine("HELLO WORLD");
        var t1 = Task.Factory.StartNew(new Func<Task>(async () => await Method()))
            .Unwrap();
        Console.WriteLine("STARTED");
        t1.Wait();
        Console.WriteLine("COMPLETED");
        Console.ReadKey();
    }
    
    static async Task Method()
    {
        // this method is perfectly safe to use async / await keywords
        Console.WriteLine("BEFORE DELAY");
        await Task.Delay(1000);
        Console.WriteLine("AFTER DELAY");
    }
    
    static void Main(字符串[]args)
    {
    Console.WriteLine(“你好世界”);
    var t1=Task.Factory.StartNew(新函数(异步()=>await方法())
    .Unwrap();
    Console.WriteLine(“已启动”);
    t1.等待();
    控制台。写入线(“已完成”);
    Console.ReadKey();
    }
    静态异步任务方法()
    {
    //此方法使用async/await关键字是完全安全的
    控制台写入线(“延迟前”);
    等待任务。延迟(1000);
    控制台写入线(“延迟后”);
    }
    
    这对我来说就像预期的那样,它打印出所有方法在3秒钟后都被执行到控制台。除非我在main中取消对Console.WriteLine的注释,否则我在3秒钟后在控制台上什么也得不到。通常,您应该避免使用
    async void
    方法,因为无法等待它们的完成。但是在这个特定的例子中,您的代码可以正常工作(除非在睡眠完成之前按Enter键)。取消注释也可以正常工作:)我在方法()中的WriteLine上插入了一个断点。线程似乎到达了那里,但由于某种原因,控制台上没有显示。为什么会发生这种情况为什么需要调用
    Task.Run
    ?Hero,Task.Run(()=>Method()).Wait();工作完美你为什么要创建另一个任务?
    Method
    返回的任务不够好吗?我需要封装一个任务,以便使用它的SynchronizationContext,如果我不这样做,根据当前的上下文,“Completed”文本将能够在“After Delay”之前显示@Servy抱歉,这是真的,我也不想让人们混淆事情,但在使用任务时这是一个“技巧”“打开“方法然后发生的所有事情都尊重async/await关键字。@J.Lennon,在控制台应用程序上没有
    SynchronizationContext
    。即使打开了,
    SynchronizationContext
    使用的是编译器在
    async
    /
    wait
    @J.Lennon时生成的状态机
    Unwrap
    需要向右滚动才能看到。因为它是唯一没有显示在屏幕上的东西,所以我没有注意到它。也就是说,您的
    async
    匿名方法仍然毫无意义。如果您只编写
    t1=Method(),代码将更加简单、可读且有效