Bildiğiniz gibi, VS11'de derleyici bir async Main
yönteme izin vermeyecektir . Bu, Async CTP ile VS2010'da izin verildi (ancak asla tavsiye edilmedi).
Özellikle async / await ve asenkron konsol programları ile ilgili son blog yayınlarım var . Giriş yazısından bazı arka plan bilgileri:
"Bekliyor", beklemenin tamamlanmadığını görürse, eşzamansız olarak hareket eder. Tamamlandığında yöntemin geri kalanını çalıştırmayı bekler ve ardından zaman uyumsuz yöntemden döner . Await, yöntemin geri kalanını beklenebilir duruma geçirdiğinde mevcut bağlamı da yakalayacaktır .
Daha sonra, beklenen işlem tamamlandığında, async yönteminin geri kalanını (yakalanan bağlam dahilinde) yürütür.
Konsol programlarında aşağıdakilere neden olan bir sorundur async Main
:
Giriş yazımızdan, bir zaman uyumsuz yöntemin tamamlanmadan önce arayanına döneceğini unutmayın . Bu, UI uygulamalarında (yöntem yalnızca UI olay döngüsüne geri döner) ve ASP.NET uygulamalarında (yöntem iş parçacığını döndürür ancak isteği canlı tutar) mükemmel çalışır. Konsol programları için pek işe yaramaz: Ana işletim sistemine döner - böylece programınız kapanır.
Çözümlerden biri, kendi içeriğinizi sağlamaktır - konsol programınız için zaman uyumsuz uyumlu bir "ana döngü".
Eğer zaman uyumsuz CTP ile bir makine varsa, kullanabilirsiniz GeneralThreadAffineContext
gelen Belgelerim \ Microsoft Visual Studio Async CTP \ Numuneler (C # Test) Birim Testi \ AsyncTestUtilities . Alternatif olarak, kullanabilirsiniz AsyncContext
dan benim Nito.AsyncEx Nuget paketinde .
İşte bir örnek AsyncContext
; GeneralThreadAffineContext
neredeyse aynı kullanıma sahiptir:
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();
}
}
Alternatif olarak, zaman uyumsuz çalışmanız tamamlanana kadar ana Konsol iş parçacığını engelleyebilirsiniz:
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();
}
}
Kullanımı GetAwaiter().GetResult()
; bu, veya AggregateException
kullanırsanız gerçekleşen sargıyı önler .Wait()
Result
Güncelleme, 2017/11/30: Visual Studio 2017 Güncelleme 3 (15.3) itibariyle dil artık destekler async Main
- sürece döner olarak Task
veya Task<T>
. Şimdi bunu yapabilirsiniz:
class Program
{
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
Anlambilim GetAwaiter().GetResult()
, ana iş parçacığını engelleme stiliyle aynı görünmektedir . Bununla birlikte, C # 7.1 için henüz bir dil spesifikasyonu yoktur, bu yüzden bu sadece bir varsayımdır.