学习笔记 --C#基础其他知识点(同步和异步)

C#中的同步和异步《一》

以下理解借鉴博客:借鉴博客地址1

异步编程(Asynchronous)

允许任务在后台执行,而不会阻塞调用线程。C#使用async和await关键字

async Task AsynchronousMethod()
{
    // 等待异步操作完成
    await Task.Delay(1000); // 模拟耗时操作
    Console.WriteLine("AsynchronousMethod 完成");
}
串行:

任务按照顺序一个接一个地执行,这在单线程程序中是自然的

// 同步串行
void Task1()
{
    Console.WriteLine("Task 1 is running");
}
 
void Task2()
{
    Console.WriteLine("Task 2 is running");
}
 
Task1();
Task2();
 
// 异步串行
async Task Task1Async()
{
    Console.WriteLine("Task 1 is running");
    await Task.Delay(1000); // 模拟异步操作
}
 
async Task Task2Async()
{
    Console.WriteLine("Task 2 is running");
    await Task.Delay(1000); // 模拟异步操作
}
 
async Task MainAsync()
{
    await Task1Async();
    await Task2Async();
}
 
MainAsync().GetAwaiter().GetResult(); // 运行异步方法

并行:(Parallel)

允许多个任务同时执行,通常利用多核处理器的能力。在C#中,Parallel.For、Parallel.ForEach和Parallel.Invoke等API用于并行执行。

using System.Threading.Tasks;
 
void Task1()
{
    Console.WriteLine("Task 1 is running");
}
 
void Task2()
{
    Console.WriteLine("Task 2 is running");
}
 
Parallel.Invoke(() => Task1(), () => Task2());
Parallel.For(0, 10, i =>
{
    Console.WriteLine($"并行任务 {i} 开始");
    Thread.Sleep(100); // 模拟耗时操作
    Console.WriteLine($"并行任务 {i} 完成");
});
并发(Concurrency):

并发是并行和串行在更广泛意义上的结合。它指的是多个任务同时或几乎同时执行,但不一定在物理上并行


using System.Threading;
 
void Task1()
{
    Console.WriteLine("Task 1 is running");
}
 
void Task2()
{
    Console.WriteLine("Task 2 is running");
}
 
Thread t1 = new Thread(new ThreadStart(Task1));
Thread t2 = new Thread(new ThreadStart(Task2));
 
t1.Start();
t2.Start();
 
t1.Join();
t2.Join();
死锁(Deadlock)

当两个或多个线程相互等待对方释放资源时,就会发生死锁

避免死锁的策略:1.确保所有线程以相同的顺序获取资源。2.使用锁超时机制。3.避免嵌套锁。4.使用更高级的并发控制机制,如信号量、事件或Concurrent集合。


以下理解借鉴博客:借鉴博客2

通过某种机制,让程序在等着IO的过程中,继续做点别的事,等IO的过程完成了,再回来处理IO的内容 --异步编程模型

C#中,异步编程,一个核心是指Task和Task对象,而两个关键字,就是async和await。
⭕在遇到await关键字之后,系统做了以下工作:
异步方法将被挂起
将控制权返回给调用者
使用线程池中的线程(而非额外创建新的线程)来计算await表达式的结果,所以await不会造成程序的阻塞
完成对await表达式的计算之后,若await表达式后面还有代码则由执行await表达式的线程(不是调用方所在的线程)继续执行这些代码

⭕定义一个异步方法应满足以下几点:
使用async关键字来修饰方法
在异步方法中使用await关键字(不使用编译器会给出警告但不报错),否则异步方法会以同步方式执行
尽量不使用void作为返回类型,若希望异步方法返回void类型,请使用Task
异步方法名称以Async结尾
异步方法中不能声明使用ref或out关键字修饰的变量

模式:

//定义
async Task function()
{
  /* your code here */
}
//调用
await function();

⭕问题点:async和await的配对
在异步编程的规范中,async修饰的方法,仅仅表示这个方法在内部有可能采用异步的方式执行,CPU在执行这个方法时,会放到一个新的线程中执行。

那这个方法,最终是否采用异步执行,不决定于是否用await方式调用这个方法,而决定于这个方法内部,是否有await方式的调用。

await是什么意思?

提及Wait:Wait就是等待,异步有一个核心,是Task。而Task有一个方法,就是Wait,写法是Task.Wait()。所以,很多人把这个Wait和await混为一谈,这是错的。
C#里,Task不是专为异步准备的,它表达的是一个线程,是工作在线程池里的一个线程。异步是线程的一种应用,多线程也是线程的一种应用。Wait,以及Status、IsCanceled、IsCompleted、IsFaulted等等,是给多线程准备的方法,跟异步没有半毛钱关系。Task.Wait()是一个同步方法,用于多线程中阻塞等待。

在异步中,await表达的意思是:当前线程/方法中,await引导的方法出结果前,跳出当前线程/方法,从调用当前线程/方法的位置,去执行其它可能执行的线程/方法,并在引导的方法出结果后,把运行点拉回到当前位置继续执行;直到遇到下一个await,或线程/方法完成返回,跳回去刚才外部最后执行的位置继续执行。

await在控制异步的执行次序。那为什么要用等待这么个词呢?是因为await确实有等待结果的含义
await的第二层意思:等待拿到结果:我们需要使用func1方法的返回值。我们可以提前去执行这个方法,而不急于拿到方法的返回值,直到我们需要使用时,再用await去获取到这个返回值去使用。

这才是异步对于我们真正的用处。对于一些耗时的IO或类似的操作,我们可以提前调用,让程序可以利用执行过程中的空闲时间来完成这个操作。等到我们需要这个操作的结果用于后续的执行时,我们await这个结果。这时候,如果await的方法已经执行完成,那我们可以马上得到结果;如果没有完成,则程序将继续执行这个方法直到得到结果。

static async Task Main(string[] args)
{
    Console.WriteLine("Async proccess - start");

    Console.WriteLine("Async proccess - enter Func1");
    Task<int> f = func1();
    Console.WriteLine("Async proccess - out Func1");

    Console.WriteLine("Async proccess - done");

    int result = await f;

    Console.WriteLine("Main proccess - done");

    Console.ReadKey();
}

private static async Task<int> func1()
{
    Console.WriteLine("Func1 proccess - start");
    await Task.Run(() => Thread.Sleep(1000));
    Console.WriteLine("Func1 proccess - end");

    return 5;
}

同步方法中调用异步:

func1().GetAwaiter().GetResult();

视频学习理解3:C#:Thread / Task / async / await 【哔哩哔哩视频教程】

1.单线程做菜:

只能做一件事情:1·未完成时其它的部分会卡住

在这里插入代码片

2.Thread方法,同时做很几件事情【Thread做菜】

            Thread t = new Thread(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("素菜做好了");
                Thread.Sleep(5000);
                Console.WriteLine("荤菜做好了");

            });
            t.Start();

3.使用任务:Task实现(使用表达式去实现),与方法2差距不大,推荐Task,会自动管理线程池【Task做菜】

			Task.Run(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("素菜做好了");
                Thread.Sleep(5000);
                Console.WriteLine("荤菜做好了");
            });

4.使用任务:Task实现(使用表达式去实现),同时开启多个Task【同时做多道菜】

			Task.Run(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("素菜做好了");
            });
            Task.Run(() =>
            {
                Thread.Sleep(5000);
                Console.WriteLine("荤菜做好了");
            });

5.等待完成之后再执行下一句话【菜都做好了吃饭】

等两件事情昨晚之后再进行下一步 ==》 异步
使用await关键字 等待结束之后再往下执行,另外:函数需要使用async异步标识,但是不会卡界面

		private async void test5()
        {
            //练习5:菜都做好了吃饭
            await Task.Run(() =>			//await Task.Run里面的这些线程会同时执行
            {
                Thread.Sleep(3000);
                Console.WriteLine("素菜做好了");
                Thread.Sleep(5000);
                Console.WriteLine("荤菜做好了");
            });

            Console.WriteLine("菜都做好了,大家快来吃饭");		//知道Task.Run全部执行完之后才会执行完到这句
        }

6.如果同一时间有很多任务一起去做,可以用list,此方法函数可以不用async标注
//在

		private  void test6()
        {
            //练习6:菜都做好了吃饭  使用list
            List<Task> ts = new List<Task>();
            ts.Add(Task.Run(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("素菜做好了");
            }));

            ts.Add(Task.Run(() =>
            {
                Thread.Sleep(5000);
                Console.WriteLine("荤菜做好了");
            }));
            
			//这里表示可以等list里面的Task结束之后再进入这里
			//(传入一个委托,lambda表达式)
            Task.WhenAll(ts).ContinueWith(t =>		
            {
                Console.WriteLine("菜都做好了,大家快来吃饭");
            });
        }

视频学习理解4:winform多线程异步编程组件 【哔哩哔哩视频教程】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值