第三方同步方法在.NET 4.7.2 WPF中冻结UI



i使用WPF MVVM具有.NET 4.7.2应用程序。我使用制造商提供的库连接到机器人。不幸的是,当IP参数有故障时,它们连接到机器人的方法将停止30秒,这实质上冻结了UI。

我决定使用异步/等待解决此问题,基于此,我认为这是一个I/O结合问题,但是由于我使用的方法连接到机器人是同步的,所以我无法等待它。在示例中,我看到他们通常首先使用异步库,当第三方提供同步方法时,我找不到解决这个问题的方法。

第一个代码段不起作用,当我尝试连接时,我的UI停止了30秒。

public async Task<bool> ConnectToRobot(string ip = "")
        {
            if (FanucController.IsConnected)
                return true;
            var result = await ConnectToFanuc(ip);
            return result;
        }
private Task<bool> ConnectToFanuc(string ip)
        {
            try
            {
                ((IRobot)FanucController).Connect(ip);
                // Other code for connection
                return Task.FromResult(true);
            }
            catch
            {
                return Task.FromResult(false);
            }
        }

最终,我通过使用CPU结合示例(第二代码代码段(来解决它,但是,这并不是CPU界限的问题,因此我不确定这是否会在将来引起问题。

public async Task<bool> ConnectToRobot(string ip = "")
        {
            if (FanucController.IsConnected)
                return true;
            var result = await Task.Run(() => ConnectToFanuc(ip));
            return result;
        }
private bool ConnectToFanuc(string ip)
        {
            try
            {
                ((IRobot)FanucController).Connect(ip);
                // Other code for connection
                return true;
            }
            catch
            {
                return false;
            }
        }

有更好的方法解决这个问题吗?我应该使用异步/等待关键字以外的其他东西吗?

我认为您完全误解了.net async在做什么。

Task<T>是承诺monad的实现。

这可以在多种状态(非常简单(。

  • 不完成
  • 结束
  • 有错误

这就是异步/等待引擎的魔力。方法可以"完成"而无需结果。

Task.FromResult在第二个状态下创造了承诺。这意味着异步/等待引擎没有机会在等待结果时去做其他事情。

.net异步等待框架的一个问题是"乌龟/异步一直往下来"问题。为了使异步等待正常工作,您需要所有内容都使用新的vangenc/task实现(这是痛苦的,因为一般而言,这意味着再次重新完成整个库(。

>

为此快速工作是使用Task.Run。对于不支持异步/等待的第三方库。

,这是一个可接受的解决方法。

使用Task.Run使同步方法围绕同步方法使异步包装器被视为不良练习,除非您要卸载当前线程以防止其在等待同步方法完成时冻结。

因此,由于ConnectToFanuc在这种情况下显然不是异步,因此使用await Task.Run调用它是可行的解决方法。

请参阅此博客以获取有关此信息的更多信息。

最新更新