【问题标题】:What is the proper way to await an Asynchronous method in Program.Main( )?在 Program.Main() 中等待异步方法的正确方法是什么?
【发布时间】:2016-02-07 03:01:38
【问题描述】:

下面总是挂在最后:

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 项目时创建的默认空白表单。

我发现,如果我要注释掉 new Form1( ) 行,它运行得非常好,但是当我将行留在原处时,它会挂在最后的 await Task.Delay( ... );

为什么这种情况不断发生?从Program.Main( ) 调用异步方法的正确方法是什么?有没有可能?

编辑 1

请注意,无论DontBlock( ) 扩展是否存在(或不存在),这种情况都会持续发生。

【问题讨论】:

    标签: c# winforms asynchronous


    【解决方案1】:

    您需要创建一个应用程序循环,在 winforms 世界中,这意味着使用Application.Run。然后,该消息循环将处理发送给它的所有异步消息。如果您愿意,当然可以创建自己的消息循环,但由于您使用的是 winform 应用程序,因此您可以使用他们的。

    为什么会一直这样?

    因为你一直在同步阻塞 UI 线程,这些操作依赖于首先完成的 other UI 消息,从而造成死锁。您不需要同步阻止此类操作,并且需要有一个消息循环让您实际处理消息。

    请注意,无论DontBlock() 扩展是否存在(或不存在),这种情况都会持续发生。

    当然可以。那是因为您阻止了对DontBlock 的调用,并且将方法命名为“DontBlock”并不会使其不被阻止。您的 DontBlock 方法实际上什么都不做,除了浪费一些 CPU 周期创建一个功能与它作为参数的任务相同的任务。如果您简单地删除对该方法的所有调用,您的程序将具有相同的功能。

    【讨论】:

    • 感谢您的回答,但它提出了更多问题。如果您能进一步帮助我,我将在另一条评论中链接。
    • 没关系。我能够弄清楚 - 感谢您的帮助。
    猜你喜欢
    • 2020-08-01
    • 2019-12-10
    • 2022-01-23
    • 2020-11-06
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    相关资源
    最近更新 更多