【问题标题】:C# (async / await) loop in task block my main thread?任务中的C#(异步/等待)循环阻塞了我的主线程?
【发布时间】:2014-08-10 04:57:07
【问题描述】:
private async Task<PortalODataContext> CallConnection(Connection connection)
    {
        bool cancel = false;
        connection.Connected = true;
        var task = getConnection(connection);

        while (!cancel && !task.IsCompleted)
        {
            Thread.Sleep(100);

            if (connection.Disconected)
            {
                cancel = true;
            }
        }

        return await task;
    }

这是我在主线程上调用的函数,就像这样:

PortalODataContext portalContext = await this.CallConnection(connectionOpen);

我是异步和等待的新手,所以我只是想弄清楚为什么我的任务“CallConnection”阻塞了我的主 UI 线程......你们能帮帮我吗?

哦,还有 GetConnection :

private Task<PortalODataContext> getConnection(Connection connection)
    {            
        return Task.Factory.StartNew(() =>
        {
            try
            {
                var context = connection.ConnectToPortal();
                connection.ListTemplateLib = this.ShellModel.ConnectionManager.GetTemplateLibrarys(connection);
                connection.ListTemplateGrp = this.ShellModel.ConnectionManager.GetTemplateGroups(connection, connection.TemplateLibraryId);
                connection.ListTemplates = this.ShellModel.ConnectionManager.GetTemplates(connection, connection.TemplateGroupId);
                return context;
            }
            catch (Exception)
            {
                throw;
            }
       });

提前致谢

【问题讨论】:

  • 所以你想知道为什么你的主线程被阻塞了?
  • 是的,我想不通
  • 看起来你的实际 IO 本质上不是异步的,所以你只是在异步方法上创建同步。你真的不应该这样做。如果工作本质上是同步的,那么您应该同步进行。如果某个更高级别的方法需要,例如,将工作卸载到另一个线程以保持 UI 线程响应,他们可以这样做。

标签: c# multithreading asynchronous async-await


【解决方案1】:

当您调用异步任务时,您必须等待结果。

异步的好处是您可以在一个方法中运行两个进程,但只能在该方法内部。 在您离开该块之前,必须再次统一两个进程。这使您可以更轻松地运行不同的进程,而不必为所涉及的对象编写委托和锁。

看看here 看看异步方法中发生了什么。那里有一个图表可以帮助您阐明流程。

在您的代码中,您不需要 Threed.Sleep。 CallConnection 方法在 getConnection 返回之前不会返回任何内容。然后你可以继续你的主线程。

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    因为Thread.Sleep

    async/await 将您的方法一分为二,在 await 之前和之后。在前半部分你有一个Thread.Sleep,导致调用者线程冻结。

    用途:

    private async Task<PortalODataContext> CallConnection(Connection connection)
    {
        bool cancel = false;
        connection.Connected = true;
        var task = getConnection(connection);
    
        while (!cancel && !task.IsCompleted)
        {
            await Task.Delay(100);
    
            if (connection.Disconected)
            {
                cancel = true;
            }
        }
    
        return await task;
    }
    

    我不完全确定你想在这里实现什么。

    【讨论】:

    • 没错。老实说,我觉得所有方法都很奇怪 :) 也许是因为它只是一个摘录。
    • 当我点击我的断开连接按钮时,我正在尝试取消任务
    • @Cedric 查看task cancellation。不过,它必须是合作的。
    猜你喜欢
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2017-07-07
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多