【问题标题】:Why does Task.WaitAll hang when a form is launched directly in Main()?为什么在 Main() 中直接启动表单时 Task.WaitAll 会挂起?
【发布时间】:2018-10-18 22:38:10
【问题描述】:

我在 C# WinForms 应用程序中添加了一个闪屏表单,以便在应用程序初始化/检查更新时显示。我正在使用 Squirrel.Windows 来检查 Program.cs 中的更新。

添加启动画面后,在 Main() 中对 Task.WaitAll 的调用永远不会返回。在添加启动画面之前,此调用按预期工作。

如何确保在 Main() 中完成任务,同时在前台显示初始屏幕?

工作示例:

static void Main()
    {
        try
        {
            using (var mgr = new UpdateManager("xxxx"))
            {
                var task = mgr.UpdateApp();
                task.RunSynchronously();
                Task.WaitAll(task);
                Console.WriteLine(task.Status);
            }
        }
        catch (Exception ex)
        {
            logger.Debug(ex.Message);
        }

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new XForm());
    }

无效示例:

static void Main()
    {
        var ss = new SplashScreen();
        Application.Run(ss);
        try
        {
            using (var mgr = new UpdateManager("xxxx"))
            {
                var task = mgr.UpdateApp();
                task.RunSynchronously();
                Task.WaitAll(task);
                Console.WriteLine(task.Status);
            }
        }
        catch (Exception ex)
        {
            logger.Debug(ex.Message);
        }
        ss.Close(); 
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new XForm());
    }

我已经阅读了一堆描述 Task.WaitAll 锁定的 SO 帖子,但我无法找到对我在这里看到的现象的直接解释,即
Synchronously waiting for an async operation, and why does Wait() freeze the program here

How would I run an async Task<T> method synchronously?

我确实尝试了调用 task.RunSynchronously() 的建议,但它似乎没有任何区别。

【问题讨论】:

  • Application.Run 是一个阻塞调用,因此在ss 表单关闭之前它不会继续进入try。如果您打算做这样的事情,我会将更新代码放在ss 表单中,而不是Main 方法中。确实,您应该避免进行两次 Application.Run 调用,因为它们会设置消息循环和线程。

标签: c# winforms task message-loop


【解决方案1】:

您可以使用以下两种方法之一来解决此问题。

更改为 C# 7.1 并使您的主要方法 ASYNC 右键单击项目 > 构建 > 高级 > C# 最新次要版本

static async Task Main()
{
    try
    {
        using (var mgr = new UpdateManager("xxxx"))
        {
            await mgr.UpdateApp();
        }
    }
    catch (Exception ex)
    {
        logger.Debug(ex.Message);
    }

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new XForm());
}

或者

如果 UpdateApp 返回一个值

使用.Result

如果 UpdateApp 没有返回值

使用 .Wait()

static void Main()
{
    try
    {
        using (var mgr = new UpdateManager("xxxx"))
        {           
            mgr.UpdateApp().Wait();             
        }
    }
    catch (Exception ex)
    {
        logger.Debug(ex.Message);
    }

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new XForm());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 2021-05-14
    • 1970-01-01
    • 2021-06-09
    • 2012-02-17
    • 1970-01-01
    相关资源
    最近更新 更多