C# c将通用windows应用程序转换为异步

C# c将通用windows应用程序转换为异步,c#,asynchronous,serial-port,win-universal-app,C#,Asynchronous,Serial Port,Win Universal App,我是windows新手,我正在使用universal app做一个爱好项目。几天后,我发现连接串行端口的唯一方法是使用SerialDevice类的异步方法 我喜欢这个主题的一般建议:一旦你开始使用一个串行api,从“Main”开始将整个应用程序转换为异步将比处理与异步方法的同步调用相关的问题容易得多 然而,VS2015创建的通用应用程序包含大量生成的非异步代码,这些代码并不易于理解。我想在某个地方有一个处理这个问题的一般模式,但我找不到任何痕迹。那么我该怎么办呢?通用应用程序不被此应用程序所分隔

我是windows新手,我正在使用universal app做一个爱好项目。几天后,我发现连接串行端口的唯一方法是使用SerialDevice类的异步方法

我喜欢这个主题的一般建议:一旦你开始使用一个串行api,从“Main”开始将整个应用程序转换为异步将比处理与异步方法的同步调用相关的问题容易得多


然而,VS2015创建的通用应用程序包含大量生成的非异步代码,这些代码并不易于理解。我想在某个地方有一个处理这个问题的一般模式,但我找不到任何痕迹。那么我该怎么办呢?

通用应用程序不被此应用程序所分隔,此应用程序是异步的,并且此应用程序不是异步的,创建异步方法并不意味着您必须完全更改所有内容才能使用它们

async和await的优点之一是允许您在不冻结UI的情况下执行长时间运行的操作

Stephen Cleary的异步模式所有这些都是完全不必要的,它滥用了异步方法的用途

大多数代码不需要用异步方法包装,同步方法几乎可以处理所有事情。但是,对于长时间运行的流程,例如从web服务请求数据,最适合使用异步方法,因为它需要很长时间

重要的是,不要陷入创建数百万异步方法的不寻常模式中,找出什么是异步的,并相应地实现此功能

某些UWP API是异步的原因是因为某些进程不是瞬时的,您必须记住,在调用异步API方法时,您是在要求操作系统代表您执行操作。事实上,操作系统可能没有准备好,或者可能过载,并且可能无法立即为您的请求提供服务,因此这些方法是异步的,这确保了您的应用程序不会挂起请求

我建议你仔细阅读这篇文章

我想在某个地方有一个处理这个问题的一般模式,但我找不到任何痕迹。那我该怎么办

我的建议总是这样:

从叶子开始,识别自然的异步操作。在您的例子中,这很容易,因为在Windows通用平台中,异步操作自然只有异步API。 使用wait调用异步api。 wait的存在将要求调用方法是异步的,您应该将其返回类型从void更改为Task或从T更改为Task。 此转换使调用方法异步,因此对于调用方法的调用方,请返回步骤2。 重复此操作直到找到根方法-在Windows通用应用程序中,这通常是一个事件处理程序,必须是异步的,否则不允许是异步任务。
随着异步在代码库中的增长,您可能会遇到各种问题,例如,您不能在属性getter或构造函数中使用wait。我有一个问题。

这是新手混淆的结果

A.术语“异步函数”有三种含义:

A.1。签名中有“async”术语的函数。这个术语的唯一意义在于编译器不会将函数体中的“await”视为变量,而是将其视为await语句。它不会以任何其他方式更改签名,在这里它严格用于向后兼容

A.2。可以等待的任务类型的函数

A.3。任务类型的函数,在主体中也有等待语句

B.UI处理未被WAIT语句阻止:如果UI基础结构的一个回调正在等待WAIT语句,则仍然执行UI消息处理

因此,为了从UI方法调用async Function.2:

将“异步”术语添加到UI函数签名a.1中

b在此函数中使用wait语句调用异步库函数A.2


c以某种方式处理异步执行的结果。

异步等待模式引起的最大困惑是,该模式只不过是将函数包装到任务中,运行它并返回正在运行的任务。理解这一点非常重要,因为您并不总是希望任务自动启动

一旦您意识到这一点,理解任何异步调用都可以很容易地被这样的任务包装就不那么费劲了

    public void PersistChanges()
    {
        var saveTask = new Task(() => PersistChangesAsync());
        saveTask.Start();
    }
当然,正如在其他地方提到的,您将希望确保尽可能多地以异步方式运行异步调用,这样,例如,如果您在应用程序中有一个保存按钮,那么您将异步拾取该事件,然后调用异步PersistChangesAsync

但在我的应用程序启动时,
我可能不希望在加载基本设置、验证用户或其他任何操作之前发生任何事情,然后您甚至可以使用saveTask.RunSynchronously,尽管显然您仍然可以异步运行多个子任务,然后等待结果(如果有),或者在所有事情都完成时定义一个延续任务

我从来没有建议将所有事情都异步化。我确实建议将自然异步操作设置为异步,其中包括I/O。按名称查找串行设备的唯一方法是运行一些异步代码。我的应用程序不介意在启动过程中等待一段时间,甚至几分钟,直到此查询完成,串行设备打开或找不到/无法打开。然而,处理从同步运行异步似乎令人难以置信,并且从.net版本更改为.net版本。我理解这个过程。我的问题是如何处理基础设施生成的代码?@zzz777:您不应该更改任何自动生成的代码。没有从串行端口读取的自动生成代码。正如我在另一篇评论中所说的,处理来自除Main以外的任何同步方法的异步调用需要对线程模型有深入的理解,我在stackoverflow上找到的每个解决方案都有很长的讨论,并多次警告可能的死锁。所以我发现一直异步到Main是一种非常有吸引力的方法。根据你的说法,这也是行不通的。谢谢你的帮助。我想通用应用程序还不适合这一领域的新手——我应该使用一些旧技术作为我的业余爱好。@ZZ777:WUP应用程序中没有主应用程序;您只需使其一直异步到平台—通常是WUP应用程序的事件处理程序。