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

学习c#的第二十四天

目录

C# 事件(Event)

事件概述

如何订阅和取消订阅事件

以编程方式订阅事件

使用匿名函数订阅事件

取消订阅

如何发布符合 .NET 准则的事件

发布基于 EventHandler 模式的事件

如何在派生类中引发基类事件

如何实现接口事件

如何实现自定义事件访问器

示例


C# 事件(Event)

事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。

C# 中使用事件机制实现线程间的通信。

事件概述

事件是一种在软件开发中常用的机制,用于实现对象间的通信和协作。一个事件有两个主要的参与者:事件发布者和事件订阅者。

事件发布者是引发事件的对象或类,它定义了一个事件以及触发该事件的条件。事件发布者通过调用事件来通知其他对象事件的发生。

事件订阅者是希望接收并处理事件的对象或类。订阅者需要将自己的方法注册到事件上,以便在事件发生时被调用。这个方法被称为事件处理程序,用于处理事件发生时的逻辑。

在.NET类库中,事件通常基于EventHandler委托和EventArgs基类。EventHandler委托定义了事件处理程序方法的签名,它接受两个参数:事件发布者和包含事件数据的EventArgs对象。通过使用标准的EventHandler委托,可以方便地在事件订阅者之间共享事件处理程序。

事件的使用可以带来很多好处。它可以将代码分离为更小、更可维护的部分,并提供了一种松耦合的方式来实现对象间的通信。通过事件,可以实现多个对象对同一个事件作出响应的情况,从而提高了代码的灵活性和可扩展性。

总结起来,事件是一种在软件开发中常用的机制,用于实现对象间的通信和协作。通过事件,事件发布者可以通知事件订阅者事件的发生,并且订阅者可以对事件作出响应。事件基于委托和事件参数类,可以提供更灵活、可维护和可扩展的代码结构。

如何订阅和取消订阅事件

以编程方式订阅事件

在C#中,可以使用+=运算符以编程方式订阅事件。下面是一个简单的示例:

using System;class Program
{static void Main(string[] args){MyEventPublisher publisher = new MyEventPublisher();MyEventHandler handler = new MyEventHandler();// 订阅事件publisher.MyEvent += handler.HandleMyEvent;// 触发事件publisher.TriggerMyEvent();Console.ReadLine();}
}class MyEventPublisher
{// 定义事件public event EventHandler MyEvent;// 触发事件public void TriggerMyEvent(){MyEvent?.Invoke(this, EventArgs.Empty);}
}class MyEventHandler
{// 处理事件public void HandleMyEvent(object sender, EventArgs e){Console.WriteLine("由我的事件处理程序处理的事件");}
}

在上面的示例中,我们定义了一个名为MyEventPublisher的事件发布者类和一个名为MyEventHandler的事件处理程序类。事件发布者类包含一个名为MyEvent的事件,它是基于标准的EventHandler委托定义的。事件处理程序类包含一个名为HandleMyEvent的方法,用于处理事件。

在Main方法中,我们创建了一个事件发布者实例和一个事件处理程序实例。然后,我们使用+=运算符将事件处理程序注册到事件上。最后,我们调用TriggerMyEvent方法触发事件,并在事件处理程序中输出一条消息。

总之,在C#中,可以使用+=运算符以编程方式订阅事件。这使得我们能够动态地向事件添加处理程序,并在不再需要处理程序时将其从事件中删除。

使用匿名函数订阅事件

当需要快速订阅事件且事件处理逻辑相对简单时,使用匿名函数订阅事件是一种方便的方式。下面是一个示例,演示了如何在C#中使用匿名函数订阅事件:

using System;class Program
{static void Main(string[] args){MyEventPublisher publisher = new MyEventPublisher();// 使用匿名函数订阅事件publisher.RaiseCustomEvent += (sender, e) =>{Console.WriteLine("正在处理带有消息的自定义事件: " + e.Message);};// 触发事件publisher.TriggerCustomEvent();Console.ReadLine();}
}class MyEventPublisher
{// 定义事件public event EventHandler<CustomEventArgs> RaiseCustomEvent;// 触发事件public void TriggerCustomEvent(){OnRaiseCustomEvent(new CustomEventArgs("事件已触发"));}protected virtual void OnRaiseCustomEvent(CustomEventArgs e){RaiseCustomEvent?.Invoke(this, e);}
}// 自定义事件参数类
public class CustomEventArgs : EventArgs
{public string Message { get; }public CustomEventArgs(string message){Message = message;}
}

在上面的示例中,我们使用匿名函数来订阅RaiseCustomEvent事件。匿名函数直接定义在订阅操作中,用于处理事件的触发。这样可以避免显式地定义命名的事件处理程序方法,特别适用于只需要进行简单处理的情况。

注意:如果使用匿名函数订阅事件,事件的取消订阅过程将比较麻烦。 这种情况下若要取消订阅,请返回到该事件的订阅代码,将该匿名函数存储在委托变量中,然后将此委托添加到该事件中。 如果必须在后面的代码中取消订阅某个事件,则建议不要使用匿名函数订阅此事件。 有关匿名函数的详细信息,请参阅 Lambda 表达式。

通过匿名函数订阅事件,可以更加简洁地表示事件订阅和处理逻辑,提高代码的可读性和简洁性。

取消订阅

若要防止在引发事件时调用事件处理程序,请取消订阅该事件。 为了防止资源泄露,应在释放订户对象之前取消订阅事件。 在取消订阅事件之前,在发布对象中作为该事件的基础的多播委托会引用封装了订户的事件处理程序的委托。 只要发布对象保持该引用,垃圾回收功能就不会删除订户对象。

在C#中,取消订阅事件可以通过使用减法赋值运算符(-=)来实现。

下面是一个示例,演示了如何取消订阅之前示例中的事件:

using System;class Program
{static void Main(string[] args){MyEventPublisher publisher = new MyEventPublisher();// 定义匿名函数作为事件处理程序EventHandler<CustomEventArgs> eventHandler = (sender, e) =>{Console.WriteLine("正在处理带有消息的自定义事件: " + e.Message);};// 订阅事件publisher.RaiseCustomEvent += eventHandler;// 触发事件publisher.TriggerCustomEvent();// 取消订阅事件publisher.RaiseCustomEvent -= eventHandler;// 再次触发事件publisher.TriggerCustomEvent();Console.ReadLine();}
}class MyEventPublisher
{// 定义事件public event EventHandler<CustomEventArgs> RaiseCustomEvent;// 触发事件public void TriggerCustomEvent(){OnRaiseCustomEvent(new CustomEventArgs("事件已触发"));}protected virtual void OnRaiseCustomEvent(CustomEventArgs e){RaiseCustomEvent?.Invoke(this, e);}
}// 自定义事件参数类
public class CustomEventArgs : EventArgs
{public string Message { get; }public CustomEventArgs(string message){Message = message;}
}

在上面的示例中,我们首先定义了一个匿名函数作为事件处理程序,并将其保存在一个变量eventHandler中。然后,我们使用+=运算符订阅了RaiseCustomEvent事件,并在事件触发后又使用-=运算符取消了对事件的订阅。这样就实现了事件的订阅和取消订阅操作。

通过使用-=运算符取消订阅事件,可以避免事件处理程序继续接收事件通知,从而实现了对事件的动态管理。

注意:所有订户都取消订阅事件后,发行者类中的事件实例将设置为 null。

如何发布符合 .NET 准则的事件

发布基于 EventHandler 模式的事件

发布事件是一种常见的设计模式,它允许一个对象通知其他对象发生了某些事情。在 C# 中,可以使用 EventHandler 模式来实现事件发布。

基于 EventHandler 模式的事件发布包括以下步骤:

  1. 定义自定义事件参数类:通常情况下,事件需要携带一些数据。可以通过自定义事件参数类来实现这个功能。自定义事件参数类必须继承自 EventArgs 类,并且应该包含至少一个属性以保存事件数据。

  2. 声明委托类型:在发布类中声明一个委托类型,用于定义事件处理程序的签名。对于非泛型版本的  EventHandler 委托,无需声明,因为它已经在 System 命名空间中定义。对于泛型版本的 EventHandler<TEventArgs> 委托,则不需要自定义委托类型,而是将事件类型指定为  EventHandler <CustomEventArgs>,其中 CustomEventArgs 是第一步中定义的自定义事件参数类。

  3. 声明事件类型:在发布类中声明一个事件类型,使用步骤 2 中定义的委托类型作为事件处理程序的类型。如果使用泛型版本的 EventHandler<TEventArgs>委托,则可以直接使用  EventHandler <CustomEventArgs> 类型来声明事件。

  4. 引发事件:在发布类中编写一个受保护的虚方法,用于执行实际的事件引发操作。在这个方法中,通过调用事件类型的 Invoke 方法来触发事件,并将自定义事件参数对象传递给事件处理程序。

  5. 订阅事件:在订阅方代码中,使用 += 运算符订阅事件。订阅方可以是类、结构体、接口或委托类型。当事件引发时,所有订阅了该事件的订阅方都会接收到通知,并执行相应的事件处理程序。

下面是一个基于 EventHandler 模式的事件发布的示例代码:

// 定义自定义事件参数类
public class CustomEventArgs : EventArgs
{public string Message { get; private set; }public CustomEventArgs(string message){Message = message;}
}// 声明委托类型
public delegate void CustomEventHandler(object sender, CustomEventArgs e);// 发布类
public class MyEventPublisher
{// 声明事件类型public event CustomEventHandler RaiseCustomEvent;// 引发事件protected virtual void OnRaiseCustomEvent(CustomEventArgs e){RaiseCustomEvent?.Invoke(this, e);}// 触发事件的方法public void TriggerCustomEvent(){OnRaiseCustomEvent(new CustomEventArgs("Hello, World!"));}
}// 订阅方代码
class Program
{static void Main(string[] args){MyEventPublisher publisher = new MyEventPublisher();// 订阅事件publisher.RaiseCustomEvent += Publisher_RaiseCustomEvent;// 触发事件publisher.TriggerCustomEvent();Console.ReadLine();}// 事件处理程序private static void Publisher_RaiseCustomEvent(object sender, CustomEventArgs e){Console.WriteLine(e.Message);}
}

在上面的示例中,我们首先定义了一个自定义事件参数类 CustomEventArgs,它包含一个 Message 属性来保存事件数据。然后,我们声明了一个名为 CustomEventHandler 的委托类型,并用作 MyEventPublisher 类中 RaiseCustomEvent 事件的处理程序类型。在 MyEventPublisher 类中,我们使用 OnRaiseCustomEvent 方法来引发 RaiseCustomEvent 事件,然后在 TriggerCustomEvent 方法中调用该方法。

在 Main 方法中,我们创建 MyEventPublisher 实例 publisher,并使用 += 运算符订阅 RaiseCustomEvent 事件。之后,我们调用 publisher 的 TriggerCustomEvent 方法来触发事件。当 RaiseCustomEvent 事件被触发时,我们定义的事件处理程序 Publisher_RaiseCustomEvent 将被调用,并输出 "Hello, World!" 字符串到控制台。

如何在派生类中引发基类事件

在派生类中引发基类事件的过程与在基类中引发事件的过程类似,只需要通过基类的事件来触发即可。下面是在派生类中引发基类事件的基本步骤:

  1. 在派生类中声明一个新的事件,或者可以选择重用基类的事件。
  2. 创建一个方法来触发基类事件。

下面是一个示例代码,演示了如何在派生类中引发基类事件:

using System;// 基类
public class BaseClass
{// 声明基类事件类型public event EventHandler BaseEventRaised;// 引发基类事件的方法protected virtual void OnBaseEventRaised(EventArgs e){BaseEventRaised?.Invoke(this, e);}
}// 派生类
public class DerivedClass : BaseClass
{public void DoSomething(){// 在派生类中进行一些操作// 触发基类事件OnBaseEventRaised(EventArgs.Empty);}
}// 主程序
class Program
{static void Main(string[] args){DerivedClass derived = new DerivedClass();// 订阅基类事件derived.BaseEventRaised += BaseEvent_Handler;// 在派生类中触发事件derived.DoSomething();Console.ReadLine();}// 基类事件处理程序private static void BaseEvent_Handler(object sender, EventArgs e){Console.WriteLine("在派生类中处理的基事件。");}
}

在上面的示例中,我们首先定义了一个基类 BaseClass,它包含一个名为 BaseEventRaised 的事件以及相应的触发方法 OnBaseEventRaised。然后,我们创建了一个派生类 DerivedClass,在该类中我们调用了基类事件触发方法 OnBaseEventRaised 来触发基类事件。

在主程序中,我们创建了 DerivedClass 的实例 derived,并订阅了基类的事件 BaseEventRaised。之后,我们调用 derived 的 DoSomething 方法来触发事件。当基类事件被触发时,我们定义的事件处理程序 BaseEvent_Handler 将被调用,并输出 "在派生类中处理的基事件。" 到控制台。

通过这种方式,派生类可以很容易地引发基类中已定义的事件,从而实现事件传播和处理。

如何实现接口事件

在 C# 中,接口可以定义事件,需要使用 event关键字来标记接口中的事件。实现接口事件的类必须提供事件的实现。下面是实现接口事件的基本步骤:

  1. 定义一个包含事件的接口,并使用 event 关键字来标记事件。

  2. 实现接口的类必须提供事件的实现。为此,可以在实现类中声明一个事件,并将其与接口中的事件关联起来。

  3. 在实现类中引发事件的方法。

下面是一个示例代码,演示了如何实现接口事件:

using System;// 定义包含事件的接口
public interface IMyInterface
{event EventHandler MyEventRaised;
}// 实现接口的类
public class MyClass : IMyInterface
{// 声明事件public event EventHandler MyEventRaised;// 引发事件的方法public void RaiseEvent(){OnMyEventRaised(EventArgs.Empty);}// 触发事件的方法protected virtual void OnMyEventRaised(EventArgs e){MyEventRaised?.Invoke(this, e);}
}// 主程序
class Program
{static void Main(string[] args){MyClass myClass = new MyClass();// 订阅事件myClass.MyEventRaised += MyEventHandler;// 触发事件myClass.RaiseEvent();Console.ReadLine();}// 事件处理程序private static void MyEventHandler(object sender, EventArgs e){Console.WriteLine("我的事件处理好了。");}
}

在上面的示例中,我们首先定义了一个包含事件的接口 IMyInterface,并使用 event 关键字来标记事件。然后,我们创建了一个实现接口的类 MyClass,在该类中声明了一个名为 MyEventRaised 的事件。在 MyClass 中,我们使用 OnMyEventRaised 方法来触发 MyEventRaised 事件。

在主程序中,我们创建了 MyClass 的实例 myClass,并订阅了 MyEventRaised 事件。之后,我们调用 myClass 的 RaiseEvent 方法来触发事件。当 MyEventRaised 事件被触发时,我们定义的事件处理程序 MyEventHandler 将被调用,并输出 "我的事件处理好了。" 到控制台。

通过这种方式,我们可以在接口中定义事件,并在实现类中提供事件的实现。因此,可以轻松地将事件的行为分离到不同的类和接口中。

如何实现自定义事件访问器

事件是一种特殊的多播委托,只能从声明它的类中进行调用。 客户端代码通过提供对应在引发事件时调用的方法的引用来订阅事件。 这些方法通过事件访问器添加到委托的调用列表中,事件访问器类似于属性访问器,不同之处在于事件访问器命名为 add 和 remove。 在大多数情况下,无需提供自定义事件访问器。 如果代码中没有提供自定义事件访问器,编译器将自动添加它们。 但在某些情况下,可能需要提供自定义行为。

示例

下面的示例演示如何实现自定义的 add 和 remove 事件访问器来控制事件处理程序的添加和移除行为。

using System;public delegate void MyEventHandler(object sender, EventArgs e);public class MyClass
{private event MyEventHandler myEvent;public event MyEventHandler MyEvent{add{Console.WriteLine("添加事件处理程序");myEvent += value;}remove{Console.WriteLine("正在删除事件处理程序");myEvent -= value;}}public void DoSomething(){Console.WriteLine("正在做某事。。。");myEvent?.Invoke(this, EventArgs.Empty);}
}public class Program
{static void Main(string[] args){MyClass myObj = new MyClass();myObj.MyEvent += MyEventHandler1;myObj.MyEvent += MyEventHandler2;myObj.DoSomething();myObj.MyEvent -= MyEventHandler2;myObj.DoSomething();Console.ReadLine();}private static void MyEventHandler1(object sender, EventArgs e){Console.WriteLine("事件处理程序处理的事件1");}private static void MyEventHandler2(object sender, EventArgs e){Console.WriteLine("事件处理程序处理的事件2");}
}

在上面的示例中,我们首先声明了一个自定义委托MyEventHandler,它定义了事件处理程序的签名。

然后,我们在MyClass类中声明了一个私有的MyEventHandler类型的事件myEvent。接下来,在MyEvent属性中定义了自定义的事件访问器。

在add访问器中,我们输出添加事件处理程序的消息,并将事件处理程序添加到myEvent事件中。在remove访问器中,我们输出移除事件处理程序的消息,并将其从myEvent事件中移除。

通过自定义事件访问器,我们可以在添加和移除事件处理程序时执行自定义的逻辑。在上面的示例中,我们简单地输出一条消息,但你可以根据需要在这些访问器中添加更复杂的逻辑。

最后,在主程序中,我们创建了一个MyClass的实例myObj,并订阅了MyEvent事件。在调用myObj.DoSomething()时,事件处理程序被调用,并输出相应的消息。然后,我们使用-=操作符将一个事件处理程序从事件中移除,并再次调用myObj.DoSomething(),只有一个事件处理程序被调用。

相关文章:

学习c#的第二十四天

目录 C# 事件&#xff08;Event&#xff09; 事件概述 如何订阅和取消订阅事件 以编程方式订阅事件 使用匿名函数订阅事件 取消订阅 如何发布符合 .NET 准则的事件 发布基于 EventHandler 模式的事件 如何在派生类中引发基类事件 如何实现接口事件 如何实现自定义事…...

ELK企业级日志分析平台——logstash

部署 新建一台虚拟机elk4部署logstash [rootelk4 ~]# yum install -y jdk-11.0.15_linux-x64_bin.rpm[rootelk4 ~]# yum install -y logstash-7.6.1.rpm 命令方式 [rootelk4 bin]# /usr/share/logstash/bin/logstash -e input { stdin { } } output { stdout {} } elasticsearc…...

laravel8中常用路由使用(笔记四)

目录 1、框架路由目录统一放该目录 2、基本路由,路由都调用Route方法 3、控制器使用路由 4、路由参数 5、路由组 6、命名路由 7、命令查看当前路由列表 8、路由缓存 在Laravel 8中&#xff0c;路由定义了应用程序中接受请求的方式。它们定义了URL和相应的控制器方法之间的…...

理解 <script> 标签的 defer 和 async 属性

当我们在编写网页时&#xff0c;经常需要在 HTML 文件中引入 JavaScript 文件。这时候&#xff0c;我们通常会使用 开始 在介绍 defer 和 async 属性之前&#xff0c;我们先来看一下 <script src"path/to/script.js"></script>这段代码会在浏览器解…...

sql中group by和having的使用

group by&#xff1a;按照某个字段或者某些字段进行分组。 having&#xff1a;对分组之后的数据进行再次过滤&#xff0c;having必须和group by一起用&#xff0c;且在group by后面。 比如person表如下&#xff08;以下查询均基于此表&#xff09;&#xff1a; 1.group by 用法…...

用python自行开发的流星监控系统meteor_monitor(第二篇)

代码&#xff1a; GitHub - xingxinghuo1000/meteor_monitor_scripts 本篇为最新代码的方案介绍和使用介绍。第一篇已经过时了&#xff0c;不建议看 。只看这一篇即可。 背景 著名的流星监控软件ufocapturehd2有几个缺陷&#xff0c;不能忍 1、吃性能&#xff0c;我的工控电脑…...

Slf4j使用Logback时,Logback如何初始化

前言 Slf4j SLF4J&#xff0c;全称 Simple Logging Facade for Java&#xff0c;是一个用于Java编程语言的日志系统抽象层。它为多种现有日志框架&#xff08;例如Log4j、java.util.logging等&#xff09;提供了统一的接口, 但自身并不实现日志功能。 SLF4J 允许用户在部署时…...

css之svg 制作圆及旋转

1.代码 <template><div class"loading-box"><div class"circle-container"><svg width"75" height"75" class"move-left-to-right"><circle cx"37.5" cy"37.5" r"26&…...

学习.NET验证模块FluentValidation的基本用法(续1:其它常见用法)

FluentValidation模块支持链式验证方法调用&#xff0c;也就是说&#xff0c;除了 RuleFor(r > r.UserName).NotEmpty()调用方式之外&#xff0c;还可以将对单个属性的多种验证函数以链式调用方式串接起来&#xff0c;比如UserName属性不能为空&#xff0c;长度在5~10之间&a…...

lv11 嵌入式开发 UART实验 11

目录 1 UART帧格式详解 1.1 UART简介 1.2 通信基础 - 并行和串行 1.3 通信基础 - 单工和双工 1.4 通信基础 - 波特率 1.5 UART帧格式 2 Exynos4412下的UART控制器 2.1 引脚功能设置 2.2 阅读芯片手册 3 UART寄存器详解 3.1 引脚寄存器 3.2 串口寄存器概览 3.3 ULC…...

Ubuntu22.04下打包发布Qt5.15应用程序的方法

Qt应用编译时选择release方式编译 目的&#xff1a;debug方式编译依赖的文件会多一些&#xff0c;同时文件大小还会很大。 Notice: 所有操作都是在当前用户下&#xff0c;如果是root账户&#xff0c;需要注意加上sudo&#xff0c;否则会因为权限问题提取依赖文件失败。 准备…...

初级JVM

1、对象在哪块内存分配&#xff1f; 数组和对象在堆内存分配&#xff1b;某些对象没有逃逸出方法&#xff0c;可能被优化为在栈上分配 2、谈谈 JVM 中的常量池 JDK 1.8 开始 字符串常量池&#xff1a;存放在堆中&#xff0c;包括 String 对象执行 intern() 方法后存的地方、…...

MySQL数据库 编程入门

目录 MySQL数据库数据类型 MySQL数据库命令执行 创建用户 创建删除库 创建删除表 MySQL数据库数据类型 MySQL数据库定义了多种数据类型&#xff0c;下面是一些常见的MySQL数据类型及其对应的C/C类型&#xff1a; 整数类型&#xff1a; TINYINT&#xff1a;有符号范围-1…...

6.golang函数

函数是执行特定任务的代码块。函数接受输入&#xff0c;对输入执行一些计算&#xff0c;然后生成输出。 函数声明 在 go 中声明函数的语法是&#xff1a; func name(parameter) (result-list){//body }函数声明以func关键字开头&#xff0c;后跟name(函数名)。在括号中指定参…...

软件可靠性测试常见的方法

“测试”一般是指“为了发现程序中的错误而执行程序的过程”&#xff0c;可靠的测试性是相对重要的&#xff0c;在部分产品开始的测试阶段&#xff0c;需要的就是可靠的测试性&#xff0c;机构&#xff0c;所以存在意义较大。但是在不同的开发阶段、对于不同的人员&#xff0c;…...

C/C++字节对齐

C/C字节对齐 C/C字节对齐1.G_PACKED2.1 pack(push)2.2 pack(1) 全部例子 C/C字节对齐 1.G_PACKED #ifdef __GNUC__#define G_PACKED( __Declaration__ ) __Declaration__ __attribute__((packed)) #else#define G_PACKED( __Declaration__ ) __pragma( pack(push,1)) __Decla…...

【Android知识笔记】性能优化专题(四)

App 线程优化 线程调度原理 任意时刻,只有一个线程占用CPU,处于运行状态多线程并发:轮流获取CPU使用权JVM负责线程调度:按照特定机制分配CPU使用权线程调度模型 分时调度模型:轮流获取、均分CPU时间抢占式调度模型:优先级高的获取,JVM采用Android线程调度 nice值:Proc…...

DC电源模块的散热措施

BOSHIDA DC电源模块的散热措施 DC电源模块的散热措施可以分为以下几种&#xff1a; 1. 增加散热器&#xff1a;在DC电源模块的电路板上增加散热片或散热器&#xff0c;通过增加散热面积和散热能力来提高散热效果。 2. 增加风扇&#xff1a;在散热器的基础上增加风扇&#xff…...

uniapp H5、小程序、APP端自定义不同运行环境(开发、测试、生产)、自定义条件编译平台、以及动态修改manifest.json值讲解

文章目录 前言一、自定义条件编译平台是什么&#xff1f;二、新增自定义条件编译平台三、动态设置服务器请求地址四、动态修改manifest.json1.根目录新增文件 modifyManifest.js2.vue.config.js引入modifyManifest.js 总结示例代码 前言 企业项目开发流程上一般都要配置多个运…...

centos 显卡驱动安装(chatglm2大模型安装步骤一)

1.服务器配置 服务器系统:Centos7.9 x64 显卡:RTX3090 (24G) 2.安装环境 2.1 检查显卡驱动是否安装 输入命令:nvidia-smi(显示显卡信息) 如果有以下显示说明,已经有显卡驱动。否则需要重装。 2.2 下载显卡驱动 第一步:浏览器输入https://www.nvidia.cn/Downloa…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...