C#异步编程
2021-04-01 02:27
标签:tpc 线程 tween tps print imageview 异常 opera 警告 什么是异步编程呢?举个简单的例子: 上面这段代码中,Main方法中的代码是按照自上而下的顺序执行的。网络状况不佳时, C#5.0新增了async和await关键字,使用这两个关键字可以大大简化异步编程 使用 async 关键字可将方法、lambda 表达式或匿名方法标记为异步,即,方法中应该包含一个或多个await表达式,但async关键字本身不会创建异步操作。 这里需要注意一点,若使用async关键字标记的方法中没有使用await关键字(编译器会给出警告但不报错),那么该方法将会以同步方式执行。 定义一个异步方法应满足以下几点: 下面定义一个异步方法 从上图我们可以看到调用GetStringAsync方法时未使用await关键字,result是Task类型,我们可以通过GetType()方法来获取result的详细类型信息: 从上图可以看到result的类型全名是System.Threading.Tasks.Task 从上图我们可以看到使用await关键字时,result是string类型,而匿名方法GetStringAsync的返回类型是Task Task void The numbers in the diagram correspond to the following steps. Note 解释虽是英文,但并没有太难的单词,是可以看懂其意思的。通过上面的说明,我们可以知道: 使用一段代码来进行验证: 执行代码 从上图左侧的调用栈中可以看到,在遇到await关键字之前,异步方法 从上图我们看到,当前线程Id是1,不在线程池中。继续执行程序: 遇到await关键字后,异步方法 代码继续执行,将Main方法所在线程接挂起5秒,系统使用线程池中的线程计算await表达式的值: 从上图我们可以看到,程序已经成功计算出await表达式的值,变量result的Status属性值变成了 再看此时的工作线程信息: 我们看到,当前线程Id是5且存在于线程池中。 从这里我们可以得知异步是借助于多线程来实现的。 Task类拥有执行异步方法的两个方法: 线程是前面所说的异步(async/await)和任务(Task)的基础。和线程紧密相关的另外一个概念是进程,这里不多赘述。 线程也是对象,频繁的创建和销毁线程比较影响性能,.NET提供线程池使得我们能够复用线程对象从而避免频繁创建和销毁线程。 自己创建线程比较麻烦但能够更好的控制程序的运行,使用async/await关键字来编码显得较为简洁,但对程序的控制力度会有所降低。 Asynchronous Programming with async and await (C#) Async/Await - Best Practices in Asynchronous Programming C#异步编程 标签:tpc 线程 tween tps print imageview 异常 opera 警告 原文地址:https://www.cnblogs.com/dancicici/p/9243896.html什么是异步编程
using System.Net.Http;
using System.Threading.Tasks;
using static System.Console;
namespace Core
{
class Async
{
static void Main()
{
Start();
End();
}
static void Wait()=>WriteLine("waiting...");
static void End()=>WriteLine("end...");
static int Start()
{
WriteLine("start...");
HttpClient client = new HttpClient();
Waiting();
var result = client.GetStringAsync("https://www.visualstudio.com/");
string str = result.Result;
return str.Length;
}
}
}
Start()
方法是比较耗时(注意,这里在Start
方法中调用了异步方法GetStringAsync
,但该方法在此处是以同步方式执行的,具体原因下文会进行说明),在Start()
方法执行完毕之前,整个程序处于阻塞状态。而异步编程可以很好的解决这个问题,一句简单的话来概括异步编程就是,程序无须按照代码顺序自上而下的执行。async/await
public async Task Asy()
{
//do something...
}
定义异步方法的几点要求
StartAsync()
:static async Task
异步方法的返回类型
如果在调用匿名方法时使用了await关键字,且匿名方法的返回类型是Task
如果在调用匿名方法时使用了await关键字,且匿名方法的返回类型是Task,那么我们得到的返回类型是void。若为使用await关键字,则得到的返回类型是Task。
不建议使用void作为异步方法的返回值。
因为使用Task或Task异步方法执行流程
上图是微软官方提供的讲解异步程序执行流程的图示,并附有解释说明:
GetStringAsync returns a Task
Therefore, AccessTheWebAsync uses an await operator to suspend its progress and to yield control to the method that called AccessTheWebAsync. AccessTheWebAsync returns a Task
If GetStringAsync (and therefore getStringTask) is complete before AccessTheWebAsync awaits it, control remains inAccessTheWebAsync. The expense of suspending and then returning to AccessTheWebAsync would be wasted if the called asynchronous process (getStringTask) has already completed and AccessTheWebSync doesn‘t have to wait for the final result.
Inside the caller (the event handler in this example), the processing pattern continues. The caller might do other work that doesn‘t depend on the result from AccessTheWebAsync before awaiting that result, or the caller might await immediately. The event handler is waiting for AccessTheWebAsync, and AccessTheWebAsync is waiting for GetStringAsync.
If you are new to asynchronous programming, take a minute to consider the difference between synchronous and asynchronous behavior. A synchronous method returns when its work is complete (step 5), but an async method returns a task value when its work is suspended (steps 3 and 6). When the async method eventually completes its work, the task is marked as completed and the result, if any, is stored in the task.
在遇到awiat关键字之前,程序是按照代码顺序自上而下以同步方式执行的。
在遇到await关键字之后,系统做了以下工作:
static void Main()
{
Task
StartAsync
自上而下同步执行。注意,这里异步方法GetStringAsync
方法是被挂起的,不会造成程序的阻塞,控制权回到调用者StartAsync
中,仔细看英文解释中的第3步。
然后在Debug Console中输入System.Threading.Thread.Current
查看当前工作线程信息,以及System.Threading.Thread.CurrentThread.IsThreadPoolThread
查看当前线程是否在线程池中。StartAsync
被挂起,控制权也回到了调用者Main方法中。
从上图我们可以看到异步方法StartAsync
中的result变量的Status属性值是WaitingForActivation
,Result属性值是Not yet computed
。RanToCompletion
。完成对await表达式的计算之后,程序继续执行后面的代码(return str.Length
)。Task
Task.Run()
,Task.Run
,Task.Run
以及Task.Run
使用线程池中的线程来执行代码,它和使用await关键字的区别是:Task.Run直接使用线程池中的线程,而使用await的异步方法是在遇到await关键字后才使用多线程。Thread
ThreadPool
结语
参考文章:
async
await
走进异步编程的世界 - 开始接触 async/await
C#执行异步操作的几种方式比较和总结
thread task parallel plinq async await多线程 任务及异步编程
走进异步编程的世界 - 在 GUI 中执行异步操作版权声明