当前位置: 首页 > news >正文

c#委托、lambda、事件

Lambda

Lambda表达式是一种匿名函数,Lambda表达式通常以箭头“=>”分隔左侧的输入和右侧的输出。

(parameter_list) => { statement_block } 

parameter_list

是由一个或多个参数组成的逗号分隔列表,每个参数都包括类型和名称,可以为空。

如果只有一个参数,只写参数名即可,不用圆括号。

Func<int, int> add = y => 1 + y;

如果是多个参数,把参数放在圆括号内。

Func<int, int,int> add = (x,y) => x + y;

statement_block

是Lambda表达式的主体。statement_block表示一段代码块,它可以包含多个语句,多个语句使用大括号包裹。

如果Lambda表达式只有一句语句,statement_block不需要花括号和return语句。

Func<int, int,int> add = (x,y) => x + y;

如果是含有多条语句,必须加上花括号和return语句。

Func<int, int,int> add = (x,y) =>

{

   X = x+1;

   Y= y+1;

   Return x+y;

常用的方法

  1. Where

Where方法是IEnumerable<T>接口的扩展方法,它筛选序列中满足指定条件的元素,返回满足条件的元素序列.

 List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

var oddNumbers = numbers.Where(x => x % 2 != 0);

  1. Select

它将序列中的每个元素投影到新的形式,返回投影后的元素序列.

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

var squaredNumbers = numbers.Select(x => x * x);

  1. Orderby

按照指定的键对序列中的元素进行排序.

List<string> words = new List<string> { "apple", "banana", "cherry", "date" };

var sortedWords = words.OrderBy(x => x.Length);

  1. GroupBy

根据指定的键对序列中的元素进行分组.

 List<string> words = new List<string> { "apple", "banana", "cherry", "date" };

var groupedWords = words.GroupBy(x => x[0]);

Lambda表达式中的闭包

闭包是指一个函数能够访问并操作在它的外部作用域中定义的变量。在Lambda表达式中,可以使用闭包来访问外部作用域中的变量.

int x = 5;

Func<int, int> add = y => x + y;

Console.WriteLine(add(3));

委托
  1. 委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。
  2. 在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联。 委托可以链接在一起,一次性调用多个方法
  3. 你可以通过委托实例调用方法。
  4. 委托用于将方法作为参数传递给其他方法,可用于定义回调方法
  5. 可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。该方法可以是静态方法,也可以是实例方法。 此灵活性意味着你可以通过编程方式来更改方法调用,还可以向现有类中插入新代码。
  6.  委托类型派生自 .NET 中的 Delegate 类。 委托类型是密封的,它们不能派生自 Delegate,也不能从其派生出自定义类

简单地说:委托类似c++的函数指针。

如何使用委托

委托是一种引用类型,虽然在定义委托时与方法有些相似,但不能将其称为方法。

委托在使用时遵循三步走的原则,即定义声明委托、实例化委托以及调用委托

     public class ShowTest

    {

        public delegate void ShowDelegate(string strText);

        public Action<string> action;

        public void Show(string strText)

        {

            Console.WriteLine(strText);

        }

         public void test()

        {

            ShowDelegate showDelegate1 = new ShowDelegate(Show);

            ShowDelegate showDelegate2 = Show;

            ShowDelegate showDelegate3 = delegate (string strText)

            {

                Console.WriteLine(strText);

            };

             ShowDelegate showDelegate4 = (string strText) => { Console.WriteLine(strText); };

            string Text = "hello";

            showDelegate1(Text);

            showDelegate2.Invoke(Text);

            action = Show;

            action(Text);

        }

    }

声明委托

修饰符  delegate  返回值类型  委托名 ( 参数列表 );

如:public delegate void ShowDelegate ();

在命名空间内,但不在类内

实例化委托

方式1:通过new 创建委托实例

必须传入一个方法作为参数,否则会报错因为委托内部的构造函数,需求传递一个方法作为参数。

委托名  委托对象名 = new 委托名 ( 方法名 );

委托中传递的方法名既可以是静态方法的名称,也可以是实例方法的名称。需要注意的是,在委托中所写的方法名必须与委托定义时的返回值类型和参数列表相同。

ShowDelegate showDelegate1 = new ShowDelegate(Show);

方式2:使用赋值的方式

ShowDelegate showDelegate2 = Show;

方式3:匿名委托

ShowDelegate showDelegate3 = delegate (string strText)

{

     Console.WriteLine(strText);

};

方式4:Lambda

ShowDelegate showDelegate4 = (string strText) => { Console.WriteLine(strText); };

调用委托

方式1:直接调用委托的变量

 showDelegate1(Text);

方式2:invoke()

 showDelegate2.Invoke(Text);

匿名委托

匿名方法的意义在于:快速方便的实例化委托,不用定义具体的方法来关联委托,就是临时定义个方法(处理逻辑)与委托相关联只是在实例化委托按照下面的格式处理。

委托类型 变量名 = delegate( 形参 ) { 逻辑处理语句 };

           Func<string, string> dele = delegate (string strpa)

             {

                 string strq = "sa";

                 return strq;

             };

            dele(str);

缺点:不能在其他地方被调用,即不具有复用性。 而且,匿名方法会将自动形成闭包。当一个函数(这里称为外部函数)包含对另一个函数(内部函数)的调用时,或内部函数使用了外部函数的变量时都会形成闭包

闭包

 在C#中我们可以使用Lambda来实现闭包闭包本质是一个对象(编译后),但使用上它和方法一致。使用闭包我们就可以实现拥有私有状态的函数!

定义我们把在Lambda表达式(或匿名方法)中所引用的外部变量称为捕获变量。而捕获变量的表达式就称为闭包

捕获变量捕获的变量会在真正调用委托时“赋值”,而不是在捕获时“赋值”,即总是使用捕获变量的最新的值。

作用:内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止。 

    public class ShowTest

    {

        public Action<string> action1;

        ShowTest()

        {

            string tt = "qq";

            action1 = (string str) => { Console.WriteLine(tt + str); };

        }

        public void test()

        {

string Text = "hello";

            action1(Text);

        }

    }

泛型委托

由于单独定义委托和事件,比较繁琐,而且比较冗余,因此C#2.0提供了Action 和Func两个泛型委托,不用单独申明,拿来就可以用。

Action<T>

(1)Action 表示无参无返回值的委托

(2)Action<int,string> 表示有参,无返回值的泛型委托,最多可入参16个

(3)使用Action 就可以囊括所有无返回值委托,可以说Action事对无返回值委托的进一步包装

     public class ShowTest

    {

        public Action<string> action;

        public void Show(string strText)

        {

            Console.WriteLine(strText);

        }

        public void test()

        {

            action = Show;

//或者 通过new 创建委托实例 委托名  委托对象名 = new 委托名 ( 方法名 );

action = new Action<string>(Show);

            action(Text);

        }

}

Func<T>

(1)Func 表示有返回值的委托(必须有返回值)

(2)Func可以无参数,也可以有参数,最多16个参数,最后一个表示返回值且只有一个

(3)使用方法同delegate,Func不过是对所有的有返回值的数据进行了一个包装

    public class ShowTest

    {

        public Func<int, int,int> addfunc;

        public int add(int a,int b)

        {

            return a + b;

        }

        public void test()

        {

            addfunc = add;

            int nRet = addfunc(1, 2);

        }

    }

多播委托

通过+=绑定多个方法到这个委托,从而形成委托链。执行委托的时候,按照添加方法的顺序,依次去执行方法

注意:

1.action.BeginInvoke();会开启一个新的线程去执行委托,注册有多个方法的委托,不能使用BeginInvoke。

2.注册有多个方法的委托想要开启新线程去执行委托,可以通过action.GetInvocationList()获取到所有的委托,然后循环,每个方法执行的时候可以BeginInvoke

3.使用多播委托的时候可能会遇到一个问题,就是委托链的第一个方法报错了,导致后面的注册的方法都无法调用。解决办法:使用GetInvocationList 按照调用顺序返回此多播委托的调用列表。

   public class ShowTest

    {

        public delegate void BuySomethingDelegate();

        public void BuyWater()

        {

            Console.WriteLine("买水!");

        }

        public void BuyKFC()

        {

            Console.WriteLine("买肯德基");

        }

        public void BuyHotDog()

        {

            Console.WriteLine("买热狗");

        }

        public void test()

        {

            BuySomethingDelegate bsd = new BuySomethingDelegate(BuyWater);

            bsd += BuyHotDog;

            bsd += BuyKFC;

            bsd -= BuyHotDog;

            Delegate[] delegateArr = bsd.GetInvocationList();

            foreach (BuySomethingDelegate item in delegateArr)

            {

                try

                {

                    item.Invoke();

                }

                catch (Exception)

                {

                    Console.WriteLine($"{item.Method.Name}方法报错了!");

                }

             }

         }

     }

延伸:

Invoke

Invoke的本质只是一个方法,方法一定是要通过对象来调用的。

Control的Invoke、Delegate的Invoke

也就是说Invoke前面要么是一个控件,要么是一个委托对象。

Control的Invoke

public object Invoke(Delegate method);

public object Invoke(Delegate method, params object[] args);

Control的Invoke一般用于解决跨线程访问的问题。即在子线程中让主线程的控件调用Invoke函数,从而操作主线程的UI空间。

使用Invoke完成一个委托方法的封送,就类似于使用SendMessage阻塞

Delegate的Invoke

目的作用就是执行委托。Delegate的Invoke其实就是从线程池中调用委托方法执行Invoke是同步的方式,会卡住调用它的UI线程。

BeginInvoke

使用BeginInvoke方法封送一个委托方法,类似于使用PostMessage进行通信,这是一个异步方法。

Control的BeginInvoke

Control类上的异步调用BeginInvoke并没有开辟新的线程完成委托任务,而是让界面控件的所属线程完成委托任务的。(还是在同一线程执行)

Delegate的BeginInvoke

Delegate.BeginInvoke方法是从ThreadPool中取出的一个线程来执行这个方法,以获得异步的执行效果。(不同的线程执行)

事件

事件本质上来讲是一种特殊的多播委托

作用:C# 中常常会使用事件来实现线程之间的通信

在 C# 中,类或对象可以通过事件向其他类或对象通知发生的相关事情。这种模式通常称为发布订阅模型,发送(或引发)事件的类称为“发布者”,接收(或处理)事件的类称为“订阅者”。所以事件主要用于发布订阅者模式(即设计模式中的观察者模式)

好处:就是解耦

发布者: 一个创建了事件委托定义的对象,同时也包含了事件和委托之间的联系与具体行为。发布者的任务就是执行这些事件,并通知程序中的其它对象。

订阅者: 一个接收事件并提供事件处理程序的对象。订阅者中的方法(事件处理程序)用于分配给发布者中的委托。

 简单的来说,发布者确定何时引发事件,而订阅者确定对事件作出何种响应。

using System;

事件的声明

事件的本质还是委托,所以要声明一个事件之前必须先声明一个相对应的委托。

public delegate void PubDelegate();

在 C# 中,事件需要使用关键字 event

<Access Specifier > event <Delegate> <Event Name>

public event PubDelegate PubEvent;

事件的使用范围:

仅可以从声明事件的类(或派生类)或结构(发布服务器类)中对其进行调用

// 发布者类

public class PublisherClass

{

    // 和事件搭配的委托

    public delegate void PubDelegate();

    // 定义事件

    public event PubDelegate PubEvent;

    // 编写处理事件的具体逻辑

    public void EventHandling()

    {

        if (PubEvent == null)

        {

            Console.WriteLine("需要注册事件的啊");

        }

        else

        {

            // 执行注册的事件

            PubEvent();

        }

    }

}

// 订阅者类

public class SubscriberClass

{

    public void printout()

    {

        Console.WriteLine("执行了订阅者类中的事件。");

        Console.ReadLine();

    }

}

public class Program

{

    static void Main()

    {

        // 实例化对象

        PublisherClass p = new PublisherClass();

        SubscriberClass s = new SubscriberClass();

        // 执行事件

        p.EventHandling();

        // 注册事件

        p.PubEvent += new PublisherClass.PubDelegate(s.printout);

        // 执行事件

        p.EventHandling();  

    }

}

事件委托之EventHandler

想直接用事件且懒得去声明委托,这时候微软给我提供了一个委托叫EventHandler,主要是给事件服务的。

事件的声明就是:

public event EventHandler 事件名;

public delegate void EventHandler(object sender, EventArgs e);

object sender一般写this

EventArgs e:事件参数,如果无参数就写成EventArgs.Empty

using System;

namespace CSharplearn

{

class Program

{

static void Main(string[] args)

{

Trigger trigger = new Trigger();

trigger.TrigMethod();

}

}

class Trigger

{

public event EventHandler TrigEvent;

public void TrigMethod()

{

TrigEvent += Logic.Printer;

TrigEvent(this,EventArgs.Empty);

}

}

class Logic

{

public static void Printer(object sender,EventArgs e)

{

Console.WriteLine("Hello World");

}

}

}

泛型兄弟长这样:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

using System;

namespace CSharplearn

{

class Program

{

static void Main(string[] args)

{

Trigger trigger = new Trigger();

trigger.TrigMethod();

}

}

class Trigger

{

public event EventHandler<MyEventArgs> TrigEvent;

public void TrigMethod()

{

MyEventArgs myArgs = new MyEventArgs();

myArgs.String = "Hello Space";

TrigEvent += Logic.Printer;

TrigEvent(this, myArgs);

//或者是 TrigEvent?.Invoke(this, myArgs);

}

}

class Logic

{

public static void Printer(object sender,MyEventArgs e)

{

Console.WriteLine(e.String);

}

}

public class MyEventArgs : EventArgs

{

public string String;

}

}

事件与委托的异同:

相同点:

事件其实是一个多播委托,本质上是一样的。

不同点:

可调用位置不同:事件只能在声明事件的类中才能调用,而委托无论是在类的内部还是外部都可以调用。

可使用符号不同:事件只能使用 += 和 -= 符号来订阅和取消订阅,但是委托不仅可以使用 += 和 -= 符号还可以使用 = 符号进行方法分配。

相关文章:

c#委托、lambda、事件

Lambda Lambda表达式是一种匿名函数&#xff0c;Lambda表达式通常以箭头“>”分隔左侧的输入和右侧的输出。 (parameter_list) > { statement_block } parameter_list 是由一个或多个参数组成的逗号分隔列表&#xff0c;每个参数都包括类型和名称&#xff0c;可以为空。…...

每日一练——9×9乘法表

#include<stdio.h>int main() {int i 0; //乘数定义for (i 1; i < 9; i) //循环1到9 {int j 0;//被乘数定义for (j 1; j < i; j) //循环被乘数1到9{printf("%d*%d%2d ", i, j, i * j); 乘法}printf("\n"); 换行} return 0; }...

大白话解析LevelDB:ShardedLRUCache

文章目录 Cache 接口定义ShardedLRUCache 的实现ShardedLRUCache 的构造函数ShardedLRUCache::Insert(const Slice& key, void* value, size_t charge, void (\*deleter)(const Slice& key, void* value))ShardedLRUCache::Lookup(const Slice& key)ShardedLRUCach…...

GDOI2024游记

Day0 中午一点钟从学校出发去东莞&#xff0c;大概坐了一个多小时车&#xff0c;两点半多到酒店。住的八方精选酒店&#xff08;ljh说他们住九方精选酒店&#xff0c;乐&#xff09;&#xff0c;说的是景区酒店&#xff0c;但打开外窗&#xff0c;近处是简陋的阳台&#xff0c…...

学编程怎么样才能更快入手,编程怎么简单易学

学编程怎么样才能更快入手&#xff0c;编程怎么简单易学 一、前言 对于初学编程建议先从简单入手&#xff0c;然后再学习其他复杂的编程语言。 今天给大家分享的中文编程开发语言工具 进度条构件的用法。 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 …...

Android 通知--判断通知是否有跳转

一. 从应用层来分析 在 Android 中&#xff0c;可以通过 PendingIntent 来实现有跳转的通知和没有跳转的通知的区别。具体来说&#xff0c;有跳转的通知会设置一个 PendingIntent&#xff0c;当用户点击通知时会触发该 PendingIntent&#xff0c;打开指定的界面或执行特…...

【计算机网络】IO多路转接之poll

文章目录 一、poll函数接口二、socket就绪条件三、poll的优点四、poll的缺点五、poll使用案例--只读取数据的server服务器1.err.hpp2.log.hpp3.sock.hpp4.pollServer.hpp5.main.cc 一、poll函数接口 #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int t…...

性能比较:in和exists

当在Hive SQL中使用NOT IN和NOT EXISTS时&#xff0c;性能差异主要取决于底层数据的组织方式、数据量大小、索引的使用情况以及具体查询的复杂程度。下面是对这两种方法的性能分析&#xff1a; 1. NOT IN&#xff1a;- 工作原理&#xff1a;NOT IN子查询会逐个比较主查询中的值…...

【Java设计模式】五、建造者模式

文章目录 1、建造者模式2、案例&#xff1a;共享单车的创建3、其他用途 1、建造者模式 某个对象的构建复杂将复杂的对象的创建 和 属性赋值所分离&#xff0c;使得同样的构建过程可以创建不同的表示建造的过程和细节调用者不需要知道&#xff0c;只需要通过构建者去进行操作 …...

nginx代理minio教程 避坑过的教程 避开SignatureDoesNotMatch

本次教程使用的是单机minio进行演示&#xff0c;集群minio也和这个差不多。 按照这个教程&#xff0c;可以避开nginx代理minio之后&#xff0c;只能访问文件&#xff0c;但是通过预签名url上传文件就会报SignatureDoesNotMatch的坑 暂定如下&#xff1a; 你已经下载好miniom…...

Linux进程详细介绍

文章目录 Linux进程1、计算机体系结构和操作系统管理1.1、计算机体系结构 -- 硬件1.2、操作系统&#xff08;Operator System&#xff09; -- 软件 2、进程2.1、进程基本概念2.2、进程标识符2.2.1、获取当前进程标识符和当前进程的父进程标识符2.2.2、通过系统调用创建进程 -- …...

2024年3月产品认证基础考试简答题及答案

产品认证基础 46.产品认证的工厂检查有哪几种路线&#xff1f;各有什么优缺点&#xff1f; 答案&#xff1a;两种常用的检查路线&#xff1a; 1.按照要素或过程检查 按照认证规则规定的工厂应满足的要素要求&#xff08;包括质量保证能力要求&#xff09;&#xff0c;结合部…...

嵌入式蓝桥杯做题总结

第十二届省赛 按键代码 ——自认为比较巧妙&#xff0c;定时器3被设置为10ms进入一次中断&#xff0c;代替了HAL_Delay(10)的方法消抖&#xff1b; 运用状态机机思想实现检测多个按键检测——且分为两个状态&#xff0c;其中一个状态PB&#xff11;和PB&#xff12;的按键不…...

Spring Boot 常用注解大全

以下是Spring Boot中常用的注解及其详细解释以及相应的代码示例&#xff1a; SpringBootApplication: 这个注解用于标识一个Spring Boot应用的主类。它整合了 Configuration&#xff0c;EnableAutoConfiguration 和 ComponentScan。 SpringBootApplication public class Demo…...

(MATLAB)第十二章-数列与极限

目录 12.1 数列 12.1.1 数列求和 1. 累计求和函数sum() 2. 忽略NaN累计求和函数 nansum() 3. 求此元素位置之前的元素和函数cumsum() 4. 求梯形累计和函数cumtrapz() 12.1.2 数列求积 1. 元素连续相乘函数 prod() 2. 求累计积函数 cumprod() 3. 阶乘函数 ffactorial(n…...

OJ输入问题+准备

写在之前&#xff1a; 发现题目输入是这样的&#xff1a; 我的问题&#xff1a;如何通过空格分割这些输入的字符串并分别保存&#xff01;&#xff01;&#xff08;C语言scanf好解决一点但我选择C....&#xff09; C引入了ostringstream、istringstream、stringstream这三个类…...

软考高级:主动攻击和被动攻击概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…...

cuda python torch 虚拟环境配置

以下是Pytorch和CUDA对应的版本 以下是Pytorch和Python对应的版本 检查cuda与Python版本是否匹配 import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.empty(3,4,devicecuda))cuda 删除cuda conda uninstall cudatoolkit --forceconda u…...

激光炸弹 刷题笔记

前置知识 二维前缀和 子矩阵的和 刷题笔记 {二维前缀和}-CSDN博客 思路 参考二维前缀和 将子矩阵的和 做成动态矩阵 一个个矩阵搜索 符合要求边长 矩阵中的元素和最大值 将x1,y1用i-k,j-k表示即可 x2,y2用i&#xff0c;j表示 代码 #include<iostream> #include<…...

Vue3学习记录(三)--- 组合式API之生命周期和模板引用

一、生命周期 1、简介 ​ 生命周期&#xff0c;指的是一个 Vue 实例从创建到销毁的完整阶段&#xff0c;强调的是一个时间段。 ​ 生命周期钩子函数&#xff0c;指的是 Vue 实例提供的内置函数&#xff0c;函数的参数为一个回调函数。这些钩子函数会在实例生命周期的某些固定…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...