我有四种方法。
以下是我的代码:
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.
答案 0 :(得分:1)
使用Stephen Cleary的Nito.AsyncEx库(可通过Nuget获得)为控制台应用程序提供异步上下文。有关更多详细信息,请参见here。
您的申请可以这样写为...
class Program
{
static int Main(string[] args)
{
try
{
Console.WriteLine("The application has started");
AsyncContext.Run(() => LongRunningTaskAsync(args));
Console.WriteLine("The application has finished");
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
return -1;
}
}
static async Task LongRunningTaskAsync(string[] args)
{
Console.WriteLine("The long running task has started");
// use Task.Delay() rather than Thread.Sleep() to avoid blocking the application
await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
Console.WriteLine("The long running task has finished");
}
}
答案 1 :(得分:1)
我在您的程序中看到了几个问题。
Preform
既不是异步也不是事件处理程序,但它不会返回任务Preform
开始的任务。因此,您永远不知道它们什么时候完成,也不知道结果是什么(例外?)。您甚至可以在程序完成之前结束程序Thread.Sleep
忙于等待。如果您想四处看看是否可以做其他事情,请改用await Task.Delay(TimeSpan.FromSeconds(1))
。在您的情况下,您必须先等待编写该行的过程,才能确保已写入任何Console行。如果您在等待第一个任务之前就开始了第二个任务,那么您将不知道第一个任务已经进行了多长时间,因此您不确定是否已经将文本写入控制台。
C# 7.1 introduced async Task Main(),因此您可以使用它代替传统的void Main
。它使您免于捕获和解释由您开始使流程异步的Task抛出的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);
}
答案 2 :(得分:0)
在控制台应用程序中,可以在.Wait()
方法中使用void Main
调用。
在某些需要同步的情况下,.Wait()
可能导致死锁(ASP.NET要求进行同步或具有UI线程的XAML / WinForms进行同步),但是这里没有要进行同步的内容。 / p>
static void Main()
{
preform.Wait()
}
这将等待异步工作同步完成。您需要该方法同步运行,以便它不会尽早返回。如果您使用async void
和await
,该方法将立即返回并退出该方法,await
在Main
方法中不起作用。
我还建议使用await Task.Delay(1000);
而不是Thread.Sleep(1000);
,因为这是规范的async
空闲方式。
对于您的代码示例:
class Program
{
static void Main(string[] args)
{
preform().Wait();
Console.ReadLine();
}
public static async Task Working()
{
Console.WriteLine("Please wait, the program is running");
}
public static async Task Takingtime()
{
Console.WriteLine("This Program started");
await Task.Delay(1000);
Console.WriteLine("The Program finished");
}
public static Task preform()
{
return Task.WhenAll(
Takingtime(),
Working());
}
}
答案 3 :(得分:0)
在构造函数中使用preform().Wait()
。因此,等待呼叫。然后在preform方法中使用await Takingtime()
和await Working()
。
并且您必须将返回类型更改为Task
。