C#基础学习--异步编程

这篇具有很好参考价值的文章主要介绍了C#基础学习--异步编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

什么是异步

async/await 特性的结构

 什么是异步方法

 异步方法的控制流

await 表达式


什么是异步

启动程序时,系统会在内存中创建一个新的进程。进程是构成运行程序的资源的集合。进程是构成运行程序的资源的集合。这些资源包括虚地址空间,文件句柄和许多其他程序运行所需的东西

在进程内部,系统创建了一个称为线程的内核(kernel)对象,它代表了真正执行的程序(线程是执行进程  的简称)。一旦进程建立,系统会在Main方法的第一行语句处就开始线程的执行

C#基础学习--异步编程

 如果一个程序调用某个方法,并在等待方法执行所有处理之后才继续执行,我们就称这样的方法是同步的。这是默认的形式

async/await 特性的结构

异步的方法在处理完成之前就返回到调用方法   特性由三个部分组成:

C#基础学习--异步编程

C#基础学习--异步编程

 什么是异步方法

异步方法在完成其工作之前返回到调用方法,然后在调用方法继续执行的时候完成其工作

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

返回类型必须是下面的三种之一:

C#基础学习--异步编程

 任何返回Task<T>类型的异步方法其返回值必须为T类型或可以隐式转换为T的类型

C#基础学习--异步编程

C#基础学习--异步编程

 下面的代码使用了Thread.Sleep 方法来暂停主线程,这样它就不会在异步方法完成之前退出

C#基础学习--异步编程

 异步方法的控制流

异步方法的结构包含三个不同的区域

C#基础学习--异步编程

 当达到await 表达式时,异步方法将控制返回到调用方法。如果方法的返回类型为Task或Task<T>类型,将创建一个Task对象,表示需异步完成的任务和后续,然后将该Task返回到调用方法

C#基础学习--异步编程

C#基础学习--异步编程

await 表达式

await 表达式指定了一个异步执行的任务。语法如下,由await 关键字和一个空闲对象(陈我给任务)组成,这个任务可能是一个Task类型的对象,也可能不是。默认情况下,这个任务在当前线程异步运行

   await   task

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

代码依次输出 5 6 7 8 

C#基础学习--异步编程

using System;
using System.Threading.Tasks;

namespace Csharpzuoye
{
    static class MyClass
    {
        private static int GetSum(int i1,int i2)
        {
            return i1 + i2;
        }

        public static async Task DoworkAsync()
        {
            int value = await Task.Run(() => GetSum(5, 6));
            Console.WriteLine(value.ToString());
        }
    }

    class program
    {
        static void Main()
        {
            Task t = MyClass.DoworkAsync();
            t.Wait();
            Console.WriteLine("Press Enter Key to exit");
            Console.Read();
        }
    }
}

Lambda 函数() => GetSum(5,6) 满足 Func<TRsult> 委托,因为它没有参数,且返回单一的值。

取消一个异步操作

可以在自己的异步方法中加入这个特性,System.Threading.Task 命名空间中有两个类是为此目的而设计的:CancellationToken 和 CancellationTokenSource

C#基础学习--异步编程

C#基础学习--异步编程

using System;
using System.Threading.Tasks;
using System.Threading;

namespace Csharpzuoye
{
    class Program
    {
        static void Main()
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            CancellationToken token = cts.Token;

            MyClass mc = new MyClass();
            Task t = mc.RunAsync(token);

            //Thread.Sleep(3000);  //等待3秒
            //cts.Cancel();  //取消操作

            t.Wait();
            Console.WriteLine($"Was Cancelled : {token.IsCancellationRequested}");
        }
    }

    class MyClass
    {
        public async Task RunAsync(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }
            await Task.Run(() => CycleMethod(ct), ct);
        }

        void CycleMethod(CancellationToken ct)
        {
            Console.WriteLine("Starting CycleMethod");
            const int max = 5;
            for (int i = 0; i < max; i++)
            {
                if (ct.IsCancellationRequested)  //监控 CancellationToken
                    return;
                Thread.Sleep(1000);
                Console.WriteLine($"{i + 1} of {max} iterations completed");
            }
        }
    }

}

C#基础学习--异步编程

C#基础学习--异步编程

 取消掉这里的注释后得到以下结果:

C#基础学习--异步编程

异常处理和 await 表达式

可以像使用其他表达式那样,将 await 表达式放在 try 语句内,try ... catch ... finally 结构将按你期望的那样工作

C#基础学习--异步编程

C#基础学习--异步编程

在调用方法中同步地等待任务

调用方法可以调用任意多个异步方法并接收它们返回的 Task 对象。然后代码继续执行其他任务,但在某个节点可能会需要等待某个特殊Task 对象完成,然后再继续。为此,Task 类提供了一个实例方法 Wait ,可以在 Task 对象上调用这个方法

在下面的代码中,调用方法 DoRun 调用异步方法 CountCharacterAsync 并接收其返回的 Task<int> ,然后调用 Task 实例的 Wait 方法,等待任务 Task 结束。等结束时再显示结果信息

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Net;

namespace Csharpzuoye
{
    static class MyDownLoadString
    {
        public static void DoRun()
        {
            Task<int> t = CountCharacterAsync("http://www.illustratedcsharp.com");
            //等待任务 t 结束
            t.Wait();
            Console.WriteLine($"The task has finished,returning value {t.Result}");
        }

        private static async Task<int> CountCharacterAsync(string site)
        {
            string result = await new WebClient().DownloadStringTaskAsync(new Uri(site));
            return result.Length;
        }
    }

    class Program
    {
        static void Main()
        {
            MyDownLoadString.DoRun();
        }
    }

}

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

 重载方法

C#基础学习--异步编程

在异步方法中异步地等待任务

有时在异步方法中,会希望用 await 表达式来等待 Task,这时异步方法会返回到调用方法,但该异步方法会等待一个或所有任务完成。可以通过 Task.WhenAll 和 Task.WhenAll 方法来实现。这两种方法称为组合子

下面的代码展示了一个使用 Task.WhenAll 方法的示例。该方法异步地等待所有与之相关的 Task 完成,不会占用主线程的时间。注意,await 表达式的任务就是调用 Task.WhenAll

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Collections.Generic;

namespace Csharpzuoye
{
    class MyDownloadString
    {
        public void DoRun()
        {
            Task<int> t = CountCharacterAsync("http://www.microsoft.com", 
                "http://www.illustratedcsharp.com");
            Console.WriteLine("DoRun: Task {0} Finished", t.IsCompleted ? "" : "Not");
            Console.WriteLine("DoRun: Result = {0}", t.Result);
        }

        private async Task<int> CountCharacterAsync(string site1,string site2)
        {
            WebClient wc1 = new WebClient();
            WebClient wc2 = new WebClient();
            Task<string> t1 = wc1.DownloadStringTaskAsync(new Uri(site1));
            Task<string> t2 = wc2.DownloadStringTaskAsync(new Uri(site2));

            List<Task<string>> tasks = new List<Task<string>>();
            tasks.Add(t1);
            tasks.Add(t2);

            await Task.WhenAll(tasks);

            Console.WriteLine("    CCA: T1{0}Finished", t1.IsCompleted ? "" : "Not");
            Console.WriteLine("    CCA: T2{0}Finished", t2.IsCompleted ? "" : "Not");

            return t1.IsCompleted ? t1.Result.Length : t2.Result.Length;
        }

    }

    class Program
    {
        static void Main()
        {
            MyDownloadString ds = new MyDownloadString();
            ds.DoRun();
        }
    }

}

C#基础学习--异步编程

Task.Delay 方法

C#基础学习--异步编程

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Collections.Generic;
using System.Diagnostics;

namespace Csharpzuoye
{
    class Simple
    {
        Stopwatch sw = new Stopwatch();

        public void DoRun()
        {
            Console.WriteLine("Caller: Before call");
            ShowDelayAsync();
            Console.WriteLine("Caller: After call");
        }

        private async void ShowDelayAsync()
        {
            sw.Start();
            Console.WriteLine($"   Before Delay: {sw.ElapsedMilliseconds}");
            await Task.Delay(1000);
            Console.WriteLine($"   After Delay: {sw.ElapsedMilliseconds}");
        }
    }

    class Program
    {
        static void Main()
        {
            Simple ds = new Simple();
            ds.DoRun();
            Console.Read();
        }
    }

}

C#基础学习--异步编程

重载方法

C#基础学习--异步编程

GUI 程序中的异步操作

C#基础学习--异步编程

Task.yield

Task.yield 方法创建一个立即返回的 awaitable 。等待一个 yield 可以让异步方法在执行后续部分的同时返回到调用方法。可以将其理解成离开当前的消息队列,回到队列末尾,让处理器有时间处理其他任务

每次执行 yield 方法,线程中的其他任务就得以执行

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Collections.Generic;
using System.Diagnostics;

namespace Csharpzuoye
{
    class DoStuff
    {
        public static async Task<int> FindSeriesSum(int i1)
        {
            int sum = 0;
            for (int i = 0; i < i1; i++)
            {
                sum += i;
                if (i % 1000 == 0)
                { 
                    await Task.Yield();
                }
            }
            return sum;
        }
    }

    class Program
    {
        static void Main()
        {
            Task<int> value = DoStuff.FindSeriesSum(1_000_0000);
            CountBig(1000_000);
            CountBig(1000_000);
            CountBig(1000_000);
            CountBig(1000_000);
            Console.WriteLine($"Sum :{value.Result}");
        }

        private static void CountBig(int p)
        {
            for (int i = 0; i < p; i++) ;
            Console.WriteLine("1");
        }
    }

}

C#基础学习--异步编程

Yield 方法在 GUI 程序中非常有用,可以中断大量工作,让其他任务使用处理器

使用异步 Lambda 表达式

C#基础学习--异步编程

C#基础学习--异步编程

BackgroundWorker 类

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

并行循环

Parallel.For 循环和 Parallel.Foreach 循环。这两个结构位于 System.Threading.Tasks 命名空间中

C#基础学习--异步编程

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Collections.Generic;
using System.Diagnostics;

namespace Csharpzuoye
{
    class DoStuff
    {
        static void Main()
        {
            Parallel.For(0, 15, i =>
                Console.WriteLine($"The square of {i} is {i * i}"));
        }
    }

}

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

其他异步编程模式

C#基础学习--异步编程

C#基础学习--异步编程

BeginInvoke 和 EndInvoke

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

C#基础学习--异步编程

等待直到完成模式

在这种模式里,原始线程发起一个异步方法,做一些其他处理,然后停止并等待,直到开启的线程结束。

IAsyncResult iar = del.BeginInvoke(3,5,null,null);

     //在发起线程中异步执行方法的同时

     //在调用线程中处理一些其他事情

long result = del.EndInvoke(iar);

完整示例:

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Collections.Generic;
using System.Diagnostics;

namespace Csharpzuoye
{
    delegate long MyDel(int first, int second);  //声明委托类型

    class Program
    {
       static long Sum(int x,int y)  //声明异步方法
       {
            Console.WriteLine("           Inside Sum");
            Thread.Sleep(100);

            return x + y;
       }

        static void Main()
        {
            MyDel del = new MyDel(Sum);

            Console.WriteLine("Before BeginInvoke");
            IAsyncResult iar = del.BeginInvoke(3, 5, null, null);  //开始异步调用
            Console.WriteLine("After BeginInvoke");

            Console.WriteLine("Doing stuff");

            long result = del.EndInvoke(iar);  //等待结束并获取结果
            Console.WriteLine($"After EndInvoke:{result}");
        }
    }

}

C#基础学习--异步编程

这是旧版的结果,现在已经不支持 begininvoke 了,代码运行不了文章来源地址https://www.toymoban.com/news/detail-425220.html

到了这里,关于C#基础学习--异步编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#异步方法async/await的三种返回类型

    有群友问C#异步方法async返回值Task和void的区别?看似简单,但不容易把它们用好。在C#中的异步编程已经成为现代编程的标配,异步方法(async/await)是实现异步编程的一种常用方式。在异步方法中,可以使用 Task 或 void 作为返回类型,还可以使用ValueTask返回类型。本文将介绍

    2024年02月04日
    浏览(36)
  • defer 和 async:JavaScript异步编程的利器

    🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_ CSDN 博客专家、23年度博客之星前端领域TOP1 🕠 牛客 高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课 签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你

    2024年03月24日
    浏览(40)
  • 异步编程的概念 以及async和await的工作原理

    一、引言 二、异步编程的基本概念 三、基于任务的异步模式(TAP) 四、async和await async的工作原理: await的工作原理: 五、异步方法的编写和调用 六、异常处理 七、取消异步操作 八、性能考虑 九、案例:异步下载文件 十、结论 在.NET中,异步编程是一

    2024年04月16日
    浏览(35)
  • 前端面试:【异步编程】Callback、Promise和Async/Await

    嗨,亲爱的JavaScript探险家!在JavaScript开发的旅程中,你会经常遇到异步编程的需求。为了处理异步操作,JavaScript提供了多种机制,包括Callbacks、Promises和Async/Await。本文将深入介绍这些机制,让你能够更好地处理异步任务。 1. Callbacks:传统的异步方式 Callbacks是JavaScript中最早

    2024年02月11日
    浏览(39)
  • 前端异步编程全套:xmlhttprequest > ajax > promise > async/await

    同步与异步区别 同步:按顺序,依次执行,向服务器发送请求--客户端做其他操作 异步:分别执行,向服务器发送请求==同时执行其他操作 原生xmlhttprequest 四步骤 创建ajax对象 设定数据的传输方式(get、post),打开连接open() 获得响应数据 属性 描述 onreadystatechange 当readysta

    2024年02月01日
    浏览(36)
  • 深入理解Async/Await:从原理到实践的JavaScript异步编程指南

    理解 async/await 的原理和使用方法是理解现代JavaScript异步编程的关键。这里我会提供一个详细的实例,涵盖原理、流程、使用方法以及一些注意事项。代码注释会尽量详尽,确保你理解每个步骤。 实例:使用async/await进行异步操作 详细解释和注释: 异步函数定义: async func

    2024年02月05日
    浏览(48)
  • 一盏茶的功夫帮你彻底搞懂JavaScript异步编程从回调地狱到async/await

     🎬 江城开朗的豌豆 :个人主页  🔥  个人专栏   :《 VUE 》 《 javaScript 》 ⛺️  生活的理想,就是为了理想的生活 ! 目录 📘 1. 引言 📘 2. 使用方法 📘 3. 实现原理 📘 4. 写到最后   在深入讨论 async/await 之前,我们需要了解一下 JavaScript 的单线程和非阻塞的特性。

    2024年02月08日
    浏览(36)
  • 什么是Promise对象?它的状态有哪些?如何使用Promise处理异步操作?以及 async、await

    前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一

    2024年02月11日
    浏览(32)
  • Winform中使用HttpClient(设置最大超时响应时间)调用接口并做业务处理时界面卡住,使用async Task await异步任务编程优化

    Winform中怎样使用HttpClient调用http的get和post接口并将接口返回json数据解析为实体类: Winform中怎样使用HttpClient调用http的get和post接口并将接口返回json数据解析为实体类_winform请求http接口_霸道流氓气质的博客-CSDN博客 参考前面使用HttpClient调用http的get和post接口的小示例, 需要定

    2024年02月02日
    浏览(45)
  • c#异步编程

    1.创建任务的几种方法 2.c#Task 常用的方法 在C#中,Task类是用于表示异步操作的重要类,它提供了许多用于管理和处理异步操作的方法。以下是Task类中常用的方法: Task.Run :创建并启动一个新的任务,该任务在后台线程上执行指定的操作。 Task.Delay :创建一个在指定时间后完

    2024年02月21日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包