在控制台应用程序中使用异步和等待

2024-03-25

我有四种方法。

  1. Main:只调用preform方法
  2. 工作中:显示“请等待用户”
  3. 花费时间:需要时间执行的程序。
  4. Preform:异步调用取时间和工作方法。

以下是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncObservation
{
    class Program
    {
        static void Main(string[] args)
        {
            preform();
        }
        public static async Task Working()
        {
            Console.WriteLine("Please wait, the program is running");  
        }
        public static async Task Takingtime()
        {
            Console.WriteLine("This Program started");
            Thread.Sleep(1000);
            Console.WriteLine("The Program finished"); 
        }
        public static async void preform()
        {
            Task timer = Takingtime();
            Task wait = Working();
        }
    }
}

最后:我需要显示

This program started. 
Please wait, the program is running 
The program ended.

我发现你的程序有几个问题。

  • 虽然Preform既不是异步也不是事件处理程序,它不返回任务
  • 任务开始于Preform在完成 Preform 之前不会等待。因此你永远不知道它们什么时候完成,也不知道结果是什么(例外?)。您甚至可以在程序完成之前结束它们
  • 启动任务后,无法保证它何时运行。如果您等待任务,您只能确定语句已经执行。
  • 使用 async-await 是一种确保您的线程四处查看是否可以做有用的事情的方法,而不是在必须等待某些事情时无所事事地等待。Thread.Sleep是忙碌的等待。如果您想环顾四周看看是否可以做其他事情,请使用await Task.Delay(TimeSpan.FromSeconds(1))反而。

就您而言,在等待应该写入您的行的过程之前,您无法确定是否已写入任何控制台行。如果您在等待第一个任务之前启动第二个任务,则您不知道第一个任务已经进行了多远,因此您无法确定文本是否已写入控制台。

C# 7.1 引入了异步任务 Main() https://www.c-sharpcorner.com/article/working-with-async-main-in-c-sharp-7-1/,所以你可以用它来代替传统的void Main。它使您免于捕捉和解释AggregateException这是由您开始使进程异步的任务引发的。

如果您不想使用async Main,你当然可以使用Task.Run调用异步函数:

static void Main(string[] args)
{
    try
    {
        var preformTask = Task.Run( () => Preform() );

        DoSomethingElse();    // if needed
        preformTask.Wait();   // wait for preformTask to finish

        Console.WriteLine("Task completed; press any key to finish");
        Console.ReadKey();
    }
    catch (Exception exc) // inclusive ggregateException if one of your Task fails
    {
        ProcessException(exc)
    }
}

static async Task preform()
{
    // To be certain that the Console Line has been written: await
    await Takingtime();

    // if here, you are certain that the Line has been written,
    // or course you have lost parallel processing
    await Working();
}

为了完整性:其他功能

public static async Task Working()
{
    Console.WriteLine("Please wait, the program is running");

    // either return a completed Task, or await for it (there is a difference!
    await Task.CompletedTask;
    // or:
    return Task.CompletedTask; // do not declare async in this case
}

public static async Task Takingtime()
{
    Console.WriteLine("This Program started");

    //Use Task.Delay instead of Sleep
    await Task.Delay(TimeSpan.FromSeconds(1);   // improved readability
    Console.WriteLine("The Program finished");
}

因为等待在Preform你确定文本已经写好了。但是,您失去了一些并行性。

如果您确实希望同时执行这些过程,则无法确定何时写入文本。如果这很重要,则将应首先运行的部分(写入控制台)与应并行运行的部分(Task.Delay)分开

static async Task preform()
{
    // Do the things that should be done before parallel tasks are run
    await DoThisFirst();

    // start the Tasks that can work parallel: not sure what statements are executed first
    var taskA = DoTaskA();
    var taskB = DoTaskB();

    // if here, you are free to do something else
    // can't be sure about the status of taskA nor taskB
    DoSomethingElse();

    // if you want to do something after you know that the tasks have completed:
    // await the tasks here:
    await Task.When (new Task[] {taskA, taskB});

    // if here, you are certain that all parallel tasks have completed successfully
    // if desired fetch the return values of the Tasks:
    var returnValueA = taskA.Result;
    var returnValueB = taskB.Result;

    // do all async things of which you needed to be certain that both tasks finished
    // for example:
    await ProcessResults(returnValueA, returnValueB);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在控制台应用程序中使用异步和等待 的相关文章

随机推荐