C#学习系列相关之多线程(四)----async和await的用法

简介: C#学习系列相关之多线程(四)----async和await的用法

一、async、await用法的作用

       async用法主要是用来作为修饰符将方法作为异步方法使用,await关键字只用作为在异步方法才能使用,也就是只有当方法有async修饰后,才能在方法中使用await,await后跟Task新的任务启动。(await和async是配对使用)

二、async、await用法实例

第一个关键点:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 线程test1005
{
    public delegate void test(string s1);
    class Program
    {
         static void Main(string[] args)
        {
            test();
            for (int i = 0; i < 400; i++)
            {
                Console.Write(0);
            }
            Console.Read();
 
        }
        public async static void test()
        {
            for (int i = 0; i < 300; i++)
            {
                Console.Write(1);
            }
            await Task.Run(() =>
            {
                for (int i = 0; i < 300; i++)
                {
                    Console.Write(2);
                }
            });
            for (int i = 0; i < 300; i++)
            {
                Console.Write(3);
            }
        }
    }
}

 

       await的核心作用:如上述代码当中,我们在test函数中使用Task.Run开启新线程后,主线程和支线程交替执行,也就是输出结果为1,然后2和3交替输出,最后输出0,只是在函数内部开启支线程,并没有跳出函数。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 线程test1005
{
    public delegate void test(string s1);
    class Program
    {
         static void Main(string[] args)
        {
            test();
            for (int i = 0; i < 1000; i++)
            {
                Console.Write(0);
            }
            Console.WriteLine("0的支线程号为" + Thread.CurrentThread.ManagedThreadId);
            Console.Read();
 
        }
        public async static void test()
        {
            for (int i = 0; i < 300; i++)
            {
                Console.Write(1);
            }
            Console.WriteLine("1的支线程号为" + Thread.CurrentThread.ManagedThreadId);
             Task.Run(() =>
            {
                for (int i = 0; i < 300; i++)
                {
                    Console.Write(2);
                }
                Console.WriteLine("2的支线程号为" + Thread.CurrentThread.ManagedThreadId);
            });
            for (int i = 0; i < 300; i++)
            {
                Console.Write(3);  
            }
            Console.WriteLine("3的支线程号为" + Thread.CurrentThread.ManagedThreadId);
        }
    }
}

运行结果为:

在添加await后,当输出2的时候,会跳出test函数,2和0交替输出,等待Task.run运行完,再继续执行函数后的内容,输出结果也就是1,2和0交替输出,最后再输出3,如果0的数量比较多,则0和3也会交替输出!

总结:test中的代码在await以前的代码都是在主函数的线程中输出,但是在await以后的代码会在Task.Run的线程中运行。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 线程test1005
{
    public delegate void test(string s1);
    class Program
    {
         static void Main(string[] args)
        {
            test();
            for (int i = 0; i < 1000; i++)
            {
                Console.Write(0);
            }
            Console.WriteLine("0的支线程号为" + Thread.CurrentThread.ManagedThreadId);
            Console.Read();
 
        }
        public async static void test()
        {
            for (int i = 0; i < 300; i++)
            {
                Console.Write(1);
            }
            Console.WriteLine("1的支线程号为" + Thread.CurrentThread.ManagedThreadId);
            await Task.Run(() =>
            {
                for (int i = 0; i < 300; i++)
                {
                    Console.Write(2);
                }
                Console.WriteLine("2的支线程号为" + Thread.CurrentThread.ManagedThreadId);
            });
            for (int i = 0; i < 300; i++)
            {
                Console.Write(3);  
            }
            Console.WriteLine("3的支线程号为" + Thread.CurrentThread.ManagedThreadId);
        }
    }
}

运行结果如图:

 


 

第二个关键点:

await会返回一个结果,返回的结果类型是Task类型,当我们主函数需要该结果的result的时候,我们的代码会等待函数全部完成后才会继续执行。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 线程test1005
{
    public delegate void test(string s1);
    class Program
    {
         static void Main(string[] args)
        {
            var tt=test();
            for (int i = 0; i < 1000; i++)
            {
                Console.Write(0);
            }
            Console.WriteLine("0的支线程号为" + Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(tt.Result);
            for (int i = 0; i < 1000; i++)
            {
                Console.Write(8);
            }
            Console.Read();
 
        }
        public async static Task<int> test()
        {
            for (int i = 0; i < 300; i++)
            {
                Console.Write(1);
            }
            Console.WriteLine("1的支线程号为" + Thread.CurrentThread.ManagedThreadId);
             var result =await Task<int>.Run(() =>
            {
                for (int i = 0; i < 300; i++)
                {
                    Console.Write(2);
                }
                Console.WriteLine("2的支线程号为" + Thread.CurrentThread.ManagedThreadId);
                return 10;
            });
            for (int i = 0; i < 300; i++)
            {
                Console.Write(3);  
            }
            Console.WriteLine("3的支线程号为" + Thread.CurrentThread.ManagedThreadId);
            return result;
        }
    }
}

上述代码中当主函数中需要tt.result时,主函数代码会等待test函数运行完返回result结果后再继续执行后续代码。

运行结果为:

提示:async修饰的函数类型只有三种,void类型、Task和Task!!!

Task.Run的单独返回类型为内部运行函数的返回值T,但await修饰后的返回值为Task


相关文章
|
4月前
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
108 0
|
11月前
|
C# UED SEO
C# 异步方法async / await任务超时处理
通过使用 `Task.WhenAny`和 `Task.Delay`方法,您可以在C#中有效地实现异步任务的超时处理机制。这种方法允许您在指定时间内等待任务完成,并在任务超时时采取适当的措施,如抛出异常或执行备用操作。希望本文提供的详细解释和代码示例能帮助您在实际项目中更好地处理异步任务超时问题,提升应用程序的可靠性和用户体验。
465 3
|
12月前
|
Java C#
如何避免在C#循环中使用await
如何避免在C#循环中使用await
297 9
|
C# UED
C#一分钟浅谈:异步编程基础 (async/await)
在现代软件开发中,异步编程对于提升应用性能和响应性至关重要,尤其是在处理网络请求和文件读 异步编程允许程序在等待操作完成时继续执行其他任务,从而提高用户体验、高效利用资源,并增强并发性。在 C# 中,`async` 用于标记可能包含异步操作的方法,而 `await` 则用于等待异步操作完成。 示例代码展示了如何使用 `async` 和 `await` 下载文件而不阻塞调用线程。此外,本文还讨论了常见问题及解决方案,如不在 UI 线程上阻塞、避免同步上下文捕获以及正确处理异常。
169 0
|
安全 数据库连接 API
C#一分钟浅谈:多线程编程入门
在现代软件开发中,多线程编程对于提升程序响应性和执行效率至关重要。本文从基础概念入手,详细探讨了C#中的多线程技术,包括线程创建、管理及常见问题的解决策略,如线程安全、死锁和资源泄露等,并通过具体示例帮助读者理解和应用这些技巧,适合初学者快速掌握C#多线程编程。
195 0
|
3月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
141 0
|
3月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
4月前
|
Java 数据挖掘 调度
Java 多线程创建零基础入门新手指南:从零开始全面学习多线程创建方法
本文从零基础角度出发,深入浅出地讲解Java多线程的创建方式。内容涵盖继承`Thread`类、实现`Runnable`接口、使用`Callable`和`Future`接口以及线程池的创建与管理等核心知识点。通过代码示例与应用场景分析,帮助读者理解每种方式的特点及适用场景,理论结合实践,轻松掌握Java多线程编程 essentials。
245 5
|
8月前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
254 20