مشکل تعیین نوع 'async' برای متد 'Main' اپلیکیشن کنسول در سی شارپ
در ویژوال استودیو 2012، کامپایلر اجازه استفاده از متد async Main را نمی دهد. در نسخه 2010 ویژوال استودیو این کار مجاز بود اما استفاده از آن توصیه نشده بود. در ویژوال استودیو 2017 آپدیت 3 (15.3) امکان استفاده از متد async Main همراه سی شارپ نسخه 7 اضافه شده است.
برای اینکه متد Main بتواند به صورت غیرهمزمان کاری را انجام دهد، چندین روش وجود دارد. یکی از راههای معمول تعریف متدی مانند MainAsync است که کار را به صورت غیر همزمان انجام دهد:
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();
}
}
و در متد Main بوسیله GetAwaiter().GetResult() نتیجهی عملیات را دریافت می کنیم. این روش باعث میشود که از مشکلات مربوط به AggregateException که با استفاده از Wait() یا Result پیش میآید، جلوگیری شود.
روش دیگری که میتوانید استفاده کنید، به این شکل است که از Task.Run برای اجرای کد غیرهمزمان بهره بگیرید:
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}).GetAwaiter().GetResult();
}
}
این کد نیز بدون نیاز به کتابخانههای خارجی، به سادگی امکان اجرای موارد غیرهمزمان را فراهم میکند. با این حال، توجه داشته باشید که برای مدیریت خطاها در این رویکرد، باید از بلوکهای try/catch مناسب استفاده نمایید.
اگر چندین تست مجزا دارید میتوانید با استفاده از Task.WaitAll() یا Task.Result، منتظر دریافت تمامی تسک های اجرا شده بمانیم:
class Program
{
static void Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var getListTask = bs.GetTasksList();
Task.WaitAll(getListTask);
var list = getListTask.Result;
}
}
در اینجا نیز استفاده از GetAwaiter().GetResult() به جای WaitAll مفید است تا از بهوجود آمدن AggregateException جلوگیری شود.