简体   繁体   English

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

[英]c# converting universal windows app to async

I am new to windows and I am making a hobby project using universal app. 我是Windows的新手,我正在使用通用应用程序制作一个爱好项目。 A few days down the road I found that the only way to hook up a serial port it to use async methods from and related to SerialDevice class. 几天之后,我发现连接该串行端口以使用来自SerialDevice类并与之相关的异步方法的唯一方法。

I liked generic advise on the topic: once you got to use one serial api it will be much easier to covert whole app to async starting right from 'Main' ( http://blog.stephencleary.com/2012/02/async-and-await.html ) than deal with issues related to sync calls to async methods. 我喜欢关于该主题的一般性建议:一旦您使用了一个串行api,从“主”( http://blog.stephencleary.com/2012/02/async-和-await.html )处理与异步方法的同步调用相关的问题。

However, universal application created by VS2015 contains ton of generated non-async code that is not intended to be comprehensible. 但是,由VS2015创建的通用应用程序包含大量生成的非异步代码,这些代码并非旨在理解。 I suppose there is a general pattern somewhere do deal with this issue but I could not find any trace of it. 我想某个地方可以解决这个问题,但是我找不到任何痕迹。 So what should I do? 所以我该怎么做?

I suppose there is a general pattern somewhere do deal with this issue but I could not find any trace of it. 我想某个地方可以解决这个问题,但是我找不到任何痕迹。 So what should I do? 所以我该怎么做?

My recommendation always goes like this: 我的建议总是这样:

  1. Start with the "leaves" and identify naturally-asynchronous operations. 从“叶”开始,然后识别自然异步的操作。 In your case, this is easy, because in the Windows Universal platform, naturally-asynchronous operations only have asynchronous APIs. 在您的情况下,这很容易,因为在Windows Universal平台中,自然异步操作具有异步API。
  2. Call the asynchronous APIs with await . 使用await调用异步API。
  3. The presence of await will require the calling method to be async (and you should change its return type from void to Task or from T to Task<T> ). await的存在将要求调用方法async (并且您应将其返回类型从void更改为Task或者从T更改为Task<T> )。
  4. This transformation makes the calling method asynchronous, so go back to step (2) for it's callers. 这种转变使得调用方法异步的,所以回到步骤(2) 它的调用者。
  5. Repeat until you reach a "root" method - in a Windows Universal app, this is often an event handler, which must be async void (they're not allowed to be async Task ). 重复执行直到找到“ root”方法-在Windows Universal应用程序中,这通常是事件处理程序,该事件处理程序必须为async void (不允许它们为async Task )。

You may run into various problems as the async "grows" through your code base - eg, you can't use await in property getters or constructors. 随着async在代码库中“增长”,您可能会遇到各种问题-例如,不能在属性获取器或构造函数中使用await I have a series of posts on my blog describing techniques to work around these problems . 我的博客上一系列帖子,描述了解决这些问题的技术

Universal apps aren't separated by " this app is asynchronous ", and " this app isn't asynchronous ", creating async methods does not mean you have to change absolutely everything in order to use them. 通用的应用程序不受“ 这个程序是异步的 ”分开,“ 这个程序是不同步 ”,创建async方法并不意味着你必须按顺序使用它们改变绝对一切。

One of the benefits of async and await allows you to execute long running operations without the freezing the UI. asyncawait的好处之一是使您可以执行长时间运行的操作,而无需冻结UI。

Stephen Cleary's pattern of " async all of the things " is totally unnecessary, and it is abusing the purpose of asynchronous methods. 斯蒂芬·克莱里(Stephen Cleary)的“使所有事物异步 ”的模式是完全不必要的,它滥用了异步方法的目的。

Most code does not need to be wrapped in asynchronous methods, synchronous methods will handle almost all things just fine. 大多数代码不需要包装在异步方法中,同步方法将处理几乎所有事情。 However for long-running processes , like requesting data from a web service for example, would be best suited to an asynchronous method simply because it takes a long time. 但是,对于长时间运行的流程 (例如从Web服务请求数据),最简单的选择是异步方法,因为它需要很长时间。

It's important that you don't get consumed in the unusual pattern of creating millions of async methods, figure out what needs to be asynchronous and implement this functionality accordingly. 重要的是,不要让您沉迷于创建数百万个async方法的异常模式中,找出需要异步的内容并相应地实现此功能。

The reason why some of the UWP API is async is because some processes are not instantaneous, you have to remember that when calling an async API method, you are asking the operating system to perform actions on your behalf. 一些UWP API async的原因是,由于某些进程不是瞬时的,因此您必须记住,在调用async API方法时,您要求操作系统代表您执行操作。 The truth is, the operating system might not be ready , or may be overloaded and may not be able to serve your request instantaneously, therefore these methods are asynchronous, which ensures that your application does not hang on a request. 事实是,操作系统可能尚未准备就绪 ,或者可能已过载,并且可能无法即时满足您的请求,因此这些方法是异步的,这确保了您的应用程序不会挂在请求上。

I would recommend reading up on this here . 我建议在这里阅读。

This was a result of confusion by novice. 这是新手困惑的结果。

A. Term 'async function' has three meanings: A.术语“异步功能”具有三个含义:

A.1. A.1。 Function that has 'async' term in the signature. 在签名中具有“异步”术语的函数。 The only significance of this term is that compiler would NOT treat 'await' in the function body as a variable, but it will treat it as await statement. 该术语的唯一含义是,编译器不会将函数主体中的“ await”视为变量,而会将其视为await语句。 It does not change signature in any other way and it is here strictly for backward compatibility. 它不会以任何其他方式更改签名,此处严格是为了向后兼容。

A.2. A2。 Function of type Task that could be awaited. 可以等待的任务类型的功能。

A.3. A.3。 Function of type Task that also have await statement in the body. 任务类型的函数在主体中也具有await语句。

B. UI processing is not blocked by await statement: if one callback from UI infrastructure is waiting on await statement, UI message processing is still performed. B. UI处理不会被await语句阻止:如果来自UI基础结构的一个回调正在等待await语句,则仍将执行UI消息处理。

So in order to call async function(A.2) from UI method: 因此,为了从UI方法调用异步函数(A.2):

(a) Add 'async' term to UI function signature (A.1). (a)在UI函数签名(A.1)中添加“异步”术语。

(b) Use await statement inside this function to call asynchronous library functions (A.2) (b)在此函数内使用await语句调用异步库函数(A.2)

(c) Handle result of asynchronous execution one way or another. (c)以一种或另一种方式处理异步执行的结果。

The biggest confusion that arises from the async-await pattern is that the pattern does nothing more than wrap a function in a Task, run it and return the running Task (this is really important to understand, because you don't always want your Task to be started automatically ... ). 由async-await模式引起的最大混乱是,该模式除了将功能包装在Task中,运行它并返回正在运行的Task之外,无非(这很重要,因为您并不总是希望自己的Task自动启动...)。

Once you do realise this, it should also be less of a stretch to understand that any async call can easily be wrapped by a Task like this. 一旦意识到这一点,那么了解任何异步调用就可以轻松地被这样的Task封装起来也就不那么费劲了。

    public void PersistChanges()
    {
        var saveTask = new Task(() => PersistChangesAsync());
        saveTask.Start();
    }

Of course, as was mentioned elsewhere, you will want to make sure that you run async calls as much async as possible, so that for instance if you were to have a Save button in your application, you'd have that event picked up asynchronously and then call the asynchronous PersistChangesAsync. 当然,正如在其他地方提到的那样,您将要确保尽可能多地运行异步调用,例如,如果要在应用程序中具有“保存”按钮,则该事件将被异步接收。然后调用异步PersistChangesAsync。

But at the startup of my application, I may not want to have anything happen before the basic settings have been loaded, user has been validated or whatever, and then you could even use saveTask.RunSynchronously() (though obviously you can still run several subtasks asynchronously and then await the results (if any, or define a continuation task when everything is complete) 但是在我的应用程序启动时,我可能不希望在加载基本设置,验证用户身份或进行任何其他操作之前发生任何事情,然后甚至可以使用saveTask.RunSynchronously()(尽管显然您仍然可以运行多个异步执行子任务,然后等待结果(如果有的话,或者在完成所有操作后定义一个继续任务)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM