吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4685|回复: 18
收起左侧

[其他转载] C# 多线程与异步的使用方法笔记

  [复制链接]
Cool_Breeze 发表于 2021-5-4 13:51
本帖最后由 Cool_Breeze 于 2021-5-16 10:32 编辑

认真阅读这句话:请务必 将任务理解为工作的异步抽象,而非 在线程之上的抽象。 默认情况下,任务在当前线程上执行,且在适当时会将工作委托给操作系统。 可选择性地通过 Task.Run API  显式请求任务在独立线程上运行。

线程与异步的使用方法

使用场景

  1. 方法 AAA, BBB, CCC

  2. 在主线程不阻塞的情况下运行不同的三个方法

  3. 方法CCC需要在方法AAA完成后执行

使用线程完成

因为方法 CCC 要等待方法 AAA 完成,所以需要一个线程同步事件。

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

class Program
{
    static EventWaitHandle CCClcok = new EventWaitHandle(false, EventResetMode.ManualReset);
    static void Main()
    {
        Thread tha = new Thread(AAA);
        Thread thb = new Thread(BBB);
        Thread thc = new Thread(CCC);
        tha.Start();
        thb.Start();
        thc.Start();
        Console.WriteLine("等待所有任务完成!");
    }

    static void AAA()
    {
        int sec = 10;
        while (sec >= 1)
        {
            Console.WriteLine("方法 AAA: {0} 秒", sec);
            sec--;
            Thread.Sleep(1000);
        }
        Console.WriteLine("方法 AAA 执行完成!");
        CCClcok.Set();
    }

    static void BBB()
    {
        int sec = 5;
        while (sec >= 1)
        {
            Console.WriteLine("方法 BBB: {0} 秒", sec);
            sec--;
            Thread.Sleep(1000);
        }
    }

    static void CCC()
    {
        CCClcok.WaitOne();
        int sec = 3;
        while (sec >= 1)
        {
            Console.WriteLine("方法 CCC: {0} 秒", sec);
            sec--;
            Thread.Sleep(1000);
        }
    }
}

线程同步事件

false 表示事件为非终止状态,EventResetMode.ManualReset 表示手动重置此事件(EventWaitHandle

static EventWaitHandle CCClcok = new EventWaitHandle(false, EventResetMode.ManualReset);

方法 AAA

CCClcok.Set() 将事件状态设为终止。被阻塞线程继续 (EventWaitHandle.Set)

static void AAA()
{
    int sec = 10;
    while (sec >= 1)
    {
        Console.WriteLine("方法 AAA: {0} 秒", sec);
        sec--;
        Thread.Sleep(1000);
    }
    Console.WriteLine("方法 AAA 执行完成!");
    CCClcok.Set();
}

方法 BBB

无要求

static void BBB()
{
    int sec = 5;
    while (sec >= 1)
    {
        Console.WriteLine("方法 BBB: {0} 秒", sec);
        sec--;
        Thread.Sleep(1000);
    }
}

方法 CCC

CCClcok.WaitOne() 阻止当前线程,直到当前 WaitHandle 收到信号。(继承自 WaitHandle)[^ 1 ]

[^ 1 ]: 如果方法 AAA 没有执行 CCClcok.Set() 这里会出现死锁

static void CCC()
{
    CCClcok.WaitOne();
    int sec = 3;
    while (sec >= 1)
    {
        Console.WriteLine("方法 CCC: {0} 秒", sec);
        sec--;
        Thread.Sleep(1000);
    }
}

Main函数

线程默认为前台线程(IsBackground),所有主线程会等待所有子线程结束 (Thread

static void Main()
{
    Thread tha = new Thread(AAA);
    Thread thb = new Thread(BBB);
    Thread thc = new Thread(CCC);
    tha.Start();
    thb.Start();
    thc.Start();
    Console.WriteLine("等待所有任务完成!");
}

执行结果

Microsoft (R) Visual C# Compiler version 4.8.3761.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reser

This compiler is provided as part of the Microsoft (R

方法 AAA: 10 秒
方法 BBB: 5 秒
等待所有任务完成!
方法 BBB: 4 秒
方法 AAA: 9 秒
方法 BBB: 3 秒
方法 AAA: 8 秒
方法 AAA: 7 秒
方法 BBB: 2 秒
方法 BBB: 1 秒
方法 AAA: 6 秒
方法 AAA: 5 秒
方法 AAA: 4 秒
方法 AAA: 3 秒
方法 AAA: 2 秒
方法 AAA: 1 秒
方法 AAA 执行完成!
方法 CCC: 3 秒
方法 CCC: 2 秒
方法 CCC: 1 秒
请按任意键继续. . .

使用异步完成

  • 注意事项(asyncawait

    1. async 方法内部没有 await 关键字将以同步方法运行
    2. await 必须出现在 async 方法内部
    3. await 接一个异步对象(必须是可等待的)
  • 不能让主线程直接退出,无法查看后面运行结果!

Thread.Sleep(14000);
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        BBB();
        CCC();
        Console.WriteLine("等待所有任务完成!");
        Thread.Sleep(14000);
    }

    static async Task AAA()
    {
        int sec = 10;
        while (sec >= 1)
        {
            Console.WriteLine("方法 AAA: {0} 秒", sec);
            sec--;
            await Task.Delay(1000);
        }
        Console.WriteLine("方法 AAA 执行完成!");
    }

    static async void BBB()
    {
        int sec = 5;
        while (sec >= 1)
        {
            Console.WriteLine("方法 BBB: {0} 秒", sec);
            sec--;
            await Task.Delay(1000);
        }
    }

    static async void CCC()
    {
        await AAA();
        int sec = 3;
        while (sec >= 1)
        {
            Console.WriteLine("方法 CCC: {0} 秒", sec);
            sec--;
            await Task.Delay(1000);
        }
    }
}

方法 AAA

返回一个 Task 对象

static async Task AAA()
{
    int sec = 10;
    while (sec >= 1)
    {
        Console.WriteLine("方法 AAA: {0} 秒", sec);
        sec--;
        await Task.Delay(1000);
    }
    Console.WriteLine("方法 AAA 执行完成!");
}

方法 BBB

无需等待,可以不用返回 Task 对象

static async void BBB()
{
    int sec = 5;
    while (sec >= 1)
    {
        Console.WriteLine("方法 BBB: {0} 秒", sec);
        sec--;
        await Task.Delay(1000);
    }
}

方法 CCC

无需等待,可以不用返回 Task 对象

使用 await 等待方法 AAA 执行完毕

static async void CCC()
{
    await AAA();
    int sec = 3;
    while (sec >= 1)
    {
        Console.WriteLine("方法 CCC: {0} 秒", sec);
        sec--;
        await Task.Delay(1000);
    }
}

执行结果

Microsoft (R) Visual C# Compiler version 4.8.3761
for C# 5
Copyright (C) Microsoft Corporation. All rights r

This compiler is provided as part of the Microsof

方法 BBB: 5 秒
方法 AAA: 10 秒
等待所有任务完成!
方法 BBB: 4 秒
方法 AAA: 9 秒
方法 BBB: 3 秒
方法 AAA: 8 秒
方法 BBB: 2 秒
方法 AAA: 7 秒
方法 BBB: 1 秒
方法 AAA: 6 秒
方法 AAA: 5 秒
方法 AAA: 4 秒
方法 AAA: 3 秒
方法 AAA: 2 秒
方法 AAA: 1 秒
方法 AAA 执行完成!
方法 CCC: 3 秒
方法 CCC: 2 秒
方法 CCC: 1 秒
请按任意键继续. . .

免费评分

参与人数 4吾爱币 +7 热心值 +4 收起 理由
Xin88 + 1 谢谢@Thanks!
卡卡loveTS + 1 + 1 热心回复!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
waiting91 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Cool_Breeze 发表于 2021-5-16 09:54
本帖最后由 Cool_Breeze 于 2021-5-16 10:21 编辑

[C#] 纯文本查看 复制代码
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static Task task;
    static void Main()
    {
        Task.WaitAll(ShowTimeMain(),MonitorShowTimeStatus());
    }
    
    static async Task ShowTimeMain()
    {
        task = ShowTime();
        await task;
    }
    
    static async Task ShowTime()
    {
        await Task.Factory.StartNew
        (
            () =>
            {
                int n = 10;
                while (n >= 0)
                {
                    Console.WriteLine(DateTime.Now);
                    Thread.Sleep(1000);
                    n--;
                }
            }
        );
    }
    
    static async Task MonitorShowTimeStatus()
    {
        if (task == null)
        {
            await Task.Delay(500);
        }
        await Task.Factory.StartNew
        (
            () =>
            {
                while (true)
                {
                    Console.WriteLine(task.Status);
                    if (task.Status == TaskStatus.RanToCompletion)
                    {
                        break;
                    }
                    Thread.Sleep(500);
                }
            }
        );
    }
}


[C#] 纯文本查看 复制代码
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static Task task;
    static CancellationTokenSource timespy = new CancellationTokenSource();
    static void Main()
    {
        Task.WaitAll(ShowTimeMain(),MonitorShowTimeStatus());
    }
    
    static async Task ShowTimeMain()
    {
        task = ShowTime();
        try
        {
            await task;            
        }
        catch // 任务取消异常
        {}
    }
    
    static async Task ShowTime()
    {
        await Task.Factory.StartNew
        (
            () =>
            {
                int n = 10;
                while (n >= 0)
                {
                    if (timespy.IsCancellationRequested)
                    {
                        timespy.Token.ThrowIfCancellationRequested();
                    }
                    Console.WriteLine(DateTime.Now);
                    Thread.Sleep(1000);
                    n--;
                }
            }
            , timespy.Token
        );
    }
    
    static async Task MonitorShowTimeStatus()
    {
        if (task == null)
        {
            await Task.Delay(500);
        }
        await Task.Factory.StartNew
        (
            () =>
            {
                int n = 10;
                while (true)
                {
                    n--;
                    Console.WriteLine("{0,-2} {1}", n,task.Status);
                    if (task.Status == TaskStatus.RanToCompletion || task.Status == TaskStatus.Canceled)
                    {
                        break;
                    }
                    Thread.Sleep(500);
                    if (n == 0)
                    {
                        timespy.Cancel();
                    }
                }
            }
        );
    }
}
 楼主| Cool_Breeze 发表于 2022-5-23 18:47
lzy00 发表于 2022-5-23 10:47
await放while里是起什么作用呢

await 不管放在哪里都会等待 它 等待的任务执行完成后,再去执行await后面的语句。

这里是延时1秒中,在任务没有完成时,它在这个等待的时间内不会占用CPU,CPU可以去做其它的事情
无名大师 发表于 2021-5-4 14:02
waiting91 发表于 2021-5-4 15:02
学习学习 刚好用用

免费评分

参与人数 1吾爱币 -2 收起 理由
李玉风我爱你 -2 请勿灌水,提高回帖质量是每位会员应尽的义务!

查看全部评分

town174 发表于 2021-11-13 20:32
不错,建议将task的并发执行,取消等机制也讲下,就更完整了
zxw75192 发表于 2021-11-15 21:29
学习学习
wang65424773 发表于 2021-11-17 12:51
学习了,Thread 在挂起状态怎么直接关闭掉?
 楼主| Cool_Breeze 发表于 2021-11-17 18:11
wang65424773 发表于 2021-11-17 12:51
学习了,Thread 在挂起状态怎么直接关闭掉?

线程有个abort方法!
alphasong 发表于 2021-11-18 17:36
最好可以讲讲.net最典型的的委托
zzvzz 发表于 2022-5-2 11:08
个人还是比较喜欢看笔记的,毕竟俺也喜欢写笔记
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 03:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表