以下内容将始终挂起:
namespace WhyDoesThisAlwaysHappen {
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main( ) {
Application.EnableVisualStyles( );
Application.SetCompatibleTextRenderingDefault( false );
new Form1( );
DGApp.Start( ).DontBlock( ).GetAwaiter( ).Result( );
}
}
static class Extensions {
public static async Task DontBlock( this Task T ) {
await T.ConfigureAwait( false );
}
public static async Task<T> DontBlock<T>( this Task<T> T2 ) {
return await T2.ConfigureAwait( false );
}
}
static class DGApp {
public static async Task Start( ) {
await RegistrationTables.Instance.Initialize( ).DontBlock( );
}
}
class RegistrationTables {
private static RegistrationTables _Instance = null;
public static RegistrationTables Instance { get { return RegistrationTables._Instance ?? ( RegistrationTables._Instance = new RegistrationTables( ) ); } }
private SQL SQLTool;
public async Task Initialize( ) {
await ( this.SQLTool = new SQL( new CancellationTokenSource( ).Token ) ).ReadConnectionFile( "Foo" ).DontBlock( );
}
}
class SQL {
private CancellationToken _CT;
public SQL( CancellationToken CT ) {
this._CT = CT;
}
public async Task ReadConnectionFile( string Foo ) {
string[ ] ConnectionDetails = await FTP.ReadFile( Foo, this._CT ).DontBlock( );
}
}
static class FTP {
public static async Task<string[ ]> ReadFile( string Foo, CancellationToken CT ) {
await Task.Delay( 1000 ).DontBlock( );
return new string[ ] { };
}
}
}
Form1( )
只不过是在创建新的WinForms项目时创建的默认空白表单。
我发现,如果我要将新的Form1( )
注释掉它完全正常的行,但当我离开该行时,它会挂在最后的await Task.Delay( ... );
为什么会一直这样?从Program.Main( )
调用异步方法的正确方法是什么?它甚至可能吗?
请注意,无论DontBlock( )
扩展程序是否存在(或不存在),都会始终如此。
答案 0 :(得分:1)
您需要创建一个应用程序循环,在winforms世界中,意味着使用Application.Run
。然后,该消息循环将处理发送给它的所有异步消息。如果你愿意,你当然可以创建自己的消息循环,但由于你使用的是winform应用程序,你可以使用它们。
为什么会这种情况继续发生?
因为您始终使用依赖于其他 UI消息的操作同步阻止UI线程,从而创建死锁。您不需要同步阻止此类操作,并且有一个实际上允许处理消息的消息循环。
请注意,无论
DontBlock()
扩展程序是否存在(或不存在),都会始终如此。
当然可以。这是因为您在调用DontBlock
时阻止,并命名方法&#34; DontBlock&#34;不会阻止它。除了浪费一些CPU周期创建一个与其作为参数的任务功能相同的任务之外,您的DontBlock
方法几乎没有任何作用。如果您只是删除了对该方法的所有调用,那么您的程序将具有相同的功能。