如何在控制台应用Main方法中调用public static async void方法?
嘿,你的这段代码存在几个关键问题,先不说能不能实现连接TFS的目标,首先编译大概率就通不过,咱们来一步步拆解和修正:
先说说你当前实现的核心问题
- 首先,
GetProjects是静态方法,你却实例化了GetProjectClass对象去调用,完全没必要,直接用GetProjectClass.GetProjects()调用就行,但这不是最严重的问题。 - 核心坑点:你用了
async void作为方法返回值!async void是专门给UI事件处理器设计的,普通异步方法绝对不能用这个返回类型——因为它不会返回Task,你根本没法用.Wait()去等待它完成,看你Main里写的t.GetProjects().Wait(),编译器会直接报错,因为GetProjects()是void类型,没有.Wait()方法。 - 另外,你在
GetProjects里调用client.GetAsync(...).Result,这是同步阻塞调用异步方法,很容易导致死锁,完全违背了异步编程的初衷,应该改成await来等待异步操作完成。
正确的修改方案
第一步:修正GetProjects方法
把async void改成async Task,并且把.Result替换成await,让方法返回可等待的Task:
using System; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; namespace ConsoleApplication2 { public class GetProjectClass { // 将async void改为async Task,让方法返回可等待的任务 public static async Task GetProjects() { try { var personalaccesstoken = "PAT_FROM_WEBSITE"; using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalaccesstoken)))); // 用await替代.Result,避免死锁 using (HttpResponseMessage response = await client.GetAsync( "https://{account}.visualstudio.com/DefaultCollection/_apis/projects")) { response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseBody); } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } }
第二步:修正Program的Main方法
如果你的项目使用C# 7.1及以上版本,可以直接把Main改成异步方法,用await等待任务完成,这是最推荐的方式:
using System; using System.Threading.Tasks; namespace ConsoleApplication2 { class Program { // 改为async Task Main,支持异步等待 static async Task Main(string[] args) { // 静态方法直接调用,无需实例化对象 await GetProjectClass.GetProjects(); Console.WriteLine("finished"); Console.ReadKey(); } } }
如果你的C#版本低于7.1,没法用异步Main,可以用GetAwaiter().GetResult()来安全等待任务完成(比.Wait()更不容易触发死锁):
using System; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { GetProjectClass.GetProjects().GetAwaiter().GetResult(); Console.WriteLine("finished"); Console.ReadKey(); } } }
最后再划几个异步编程的重点
- 普通异步方法永远不要用
async void,优先用async Task(无返回值)或async Task<T>(有返回值); - 异步方法内部尽量全程用
await,不要混用.Result或.Wait()这类同步阻塞调用,避免死锁; - 控制台程序优先使用异步
Main(C#7.1+),写法更简洁安全。
内容的提问来源于stack exchange,提问作者user8074991
相关产品推荐
相关产品推荐

