gpt4 book ai didi

c# - 无法在控制台应用程序的 'async' 方法上指定 'Main' 修饰符

转载 作者:IT王子 更新时间:2023-10-29 03:27:42 28 4
gpt4 key购买 nike

我是使用 async 修饰符进行异步编程的新手。我想弄清楚如何确保我的控制台应用程序的 Main 方法实际异步运行。

class Program
{
static void Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = bs.GetList();
}
}

public class Bootstrapper {

public async Task<List<TvChannel>> GetList()
{
GetPrograms pro = new GetPrograms();

return await pro.DownloadTvChannels();
}
}

我知道这不是从“顶部”异步运行的。由于无法在 Main 方法上指定 async 修饰符,我如何在 main 中异步运行代码?

最佳答案

如您所见,在 VS11 中,编译器将不允许 async Main方法。在带有异步 CTP 的 VS2010 中,这是允许的(但从不推荐)。

更新,2017 年 11 月 30 日:自 Visual Studio 2017 更新 3 (15.3) 起,该语言现在支持 async Main - 只要它返回 TaskTask<T> .所以你现在可以这样做:

class Program
{
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}

语义似乎与 GetAwaiter().GetResult() 相同阻塞主线程的风格。但是,目前还没有针对 C# 7.1 的语言规范,因此这只是一个假设。


我最近有关于 async/await 的博文和 asynchronous console programs尤其是。以下是介绍帖子中的一些背景信息:

If "await" sees that the awaitable has not completed, then it acts asynchronously. It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method. Await will also capture the current context when it passes the remainder of the method to the awaitable.

Later on, when the awaitable completes, it will execute the remainder of the async method (within the captured context).

这就是为什么在带有 async Main 的控制台程序中出现问题的原因:

Remember from our intro post that an async method will return to its caller before it is complete. This works perfectly in UI applications (the method just returns to the UI event loop) and ASP.NET applications (the method returns off the thread but keeps the request alive). It doesn't work out so well for Console programs: Main returns to the OS - so your program exits.

一个解决方案是为您的控制台程序提供一个异步兼容的“主循环”。

如果您有一台带有异步 CTP 的机器,您可以使用 GeneralThreadAffineContext来自 My Documents\Microsoft Visual Studio Async CTP\Samples(C# Testing) Unit Testing\AsyncTestUtilities。或者,您可以使用 AsyncContext 来自 my Nito.AsyncEx NuGet package .

这是一个使用 AsyncContext 的例子; GeneralThreadAffineContext用法几乎相同:

using Nito.AsyncEx;
class Program
{
static void Main(string[] args)
{
AsyncContext.Run(() => MainAsync(args));
}

static async void MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}

或者,您可以阻塞主控制台线程,直到您的异步工作完成:

class Program
{
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}

static async Task MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}

注意 GetAwaiter().GetResult() 的使用;这避免了 AggregateException如果你使用 Wait() 就会发生包装或 Result .

关于c# - 无法在控制台应用程序的 'async' 方法上指定 'Main' 修饰符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9208921/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com