Tuple

可以通过nuget安装 NetLegacySupport.Tuple。这是从.Net 4.5移植到.Net 2.0和3.5的Tuple类 下面是一个使用 Tuple 的简单示例: using System; class Program { static void Main(string[] args) { // 创建一个包含两个元素的 Tuple var tuple = Tuple.Create("John", 30); // 访问 Tuple 中的元素 Console.WriteLine("Name: " + tuple.Item1); Console.WriteLine("Age: " + tuple.Item2); // 创建一个包含三个元素的 Tuple var tuple2 = Tuple.Create("Mary", 25, "Female"); // 访问 Tuple 中的元素 Console.WriteLine("Name: " + tuple2.Item1); Console.WriteLine("Age: " + tuple2.Item2); Console.WriteLine("Gender: " + tuple2.Item3); } } 在上面的示例中,我们使用 Tuple.Create 方法创建了两个不同元素数量的 Tuple,并访问了其中的元素。Tuple 的元素可以通过 Item1、Item2、Item3 等属性访问,也可以使用解构语法将元素分解成多个变量。 当我们运行上面的代码时,输出结果如下: Name: John Age: 30 Name: Mary Age: 25 Gender: Female 可以看到,我们成功地创建了两个不同元素数量的 Tuple,并成功访问了其中的元素。需要注意的是,Tuple 是一个不可变类型,一旦创建,就不能修改其元素的值。如果需要修改 Tuple 中的元素,需要先创建一个新的 Tuple。

2025年7月24日 · 1 分钟 · 88 字

.NET Framework 自托管详解

.NET Framework 自托管详解 自托管(Self-Hosting)是指不依赖 IIS 等外部 Web 服务器,而是通过应用程序自身创建和管理 Web 服务器实例的方式运行 Web 应用程序。 1. HttpListener 方式 这是最基础的自托管方式,使用 .NET Framework 内置的 HttpListener 类: using System; using System.IO; using System.Net; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { // 创建 HttpListener 实例 HttpListener listener = new HttpListener(); // 添加监听的 URL 前缀 listener.Prefixes.Add("http://localhost:8080/"); // 启动监听 listener.Start(); Console.WriteLine("服务器启动,监听 http://localhost:8080/"); // 处理请求循环 while (true) { // 等待请求 HttpListenerContext context = await listener.GetContextAsync(); // 处理请求 await ProcessRequest(context); } } static async Task ProcessRequest(HttpListenerContext context) { HttpListenerResponse response = context.Response; // 设置响应内容 string responseString = "<html><body><h1>Hello from Self-Hosted Server!</h1></body></html>"; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); // 设置响应头 response.ContentType = "text/html"; response.ContentLength64 = buffer.Length; // 写入响应 using (Stream output = response.OutputStream) { await output.WriteAsync(buffer, 0, buffer.Length); } // 关闭响应 response.Close(); } } 2. ASP.NET Web API 自托管 使用 Microsoft.AspNet.WebApi.SelfHost 包可以创建更完整的 Web API 服务: ...

2025年7月24日 · 2 分钟 · 401 字

winform程序防止多开

Winform启动的时候,检测是否存在同样的进程名,防止程序多开; static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { string processName = Process.GetCurrentProcess().ProcessName; Process[] processes = Process.GetProcessesByName(processName); //如果该数组长度大于1,说明多次运行 if (processes.Length > 1) { MessageBox.Show("程序已运行,不能再次打开!"); Environment.Exit(1); } else { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } } 利用Mutex互斥对象防止程序多开; static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { bool isAppRunning = false; Mutex mutex = new Mutex(true, System.Diagnostics.Process.GetCurrentProcess().ProcessName, out isAppRunning); if (!isAppRunning) { MessageBox.Show("程序已运行,不能再次打开!"); Environment.Exit(1); } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } }

2025年7月24日 · 1 分钟 · 82 字

.NET的版本

.NET Framework 是微软在 2002 年推出的一个软件开发框架,它提供了一组类库和运行时环境,可以用来开发 Windows 应用程序、Web 应用程序、服务端应用程序等。下面是 .NET Framework 的版本列表: .NET Framework 1.0 .NET Framework 1.1 .NET Framework 2.0 .NET Framework 3.0 .NET Framework 3.5 .NET Framework 4.0 .NET Framework 4.5 .NET Framework 4.5.1 .NET Framework 4.5.2 .NET Framework 4.6 .NET Framework 4.6.1 .NET Framework 4.6.2 .NET Framework 4.7 .NET Framework 4.7.1 .NET Framework 4.7.2 .NET Framework 4.8 除了 .NET Framework,微软还推出了 .NET Core 和 .NET 5,它们是跨平台的 .NET 实现,可以在 Windows、Linux 和 macOS 上运行。下面是 .NET Core 和 .NET 5 的版本列表: .NET Core 1.0 .NET Core 1.1 .NET Core 2.0 .NET Core 2.1 .NET Core 2.2 .NET Core 3.0 .NET Core 3.1 .NET 5.0 需要注意的是,.NET Framework 和 .NET Core 是两个不同的产品,它们有不同的类库和运行时环境,并且不完全兼容。同时,.NET 5 是 .NET Core 的后继版本,它将 .NET Framework、.NET Core 和 Xamarin 合并为一个平台。

2025年7月24日 · 1 分钟 · 119 字

程序进程间通讯的方法

在编程中,有几种常见的方法可以实现程序进程间的通信,包括: 管道(Pipes):管道是一种在两个进程之间传递数据的通信机制。它可以是匿名管道(在同一台计算机上的进程之间使用)或命名管道(在网络上的不同计算机之间使用)。 套接字(Sockets):套接字是一种通过网络在不同计算机上的进程之间进行通信的方法。它可以使用TCP协议(面向连接)或UDP协议(无连接)。 共享内存(Shared Memory):共享内存是一种在不同进程之间共享数据的机制。它允许多个进程访问同一块内存区域,从而实现数据的快速交换。 消息队列(Message Queues):消息队列是一种通过在进程之间传递消息来实现通信的机制。它可以是基于内存的消息队列或持久化的消息队列。 文件(Files):进程可以通过读写共享文件来进行通信。一个进程可以将数据写入文件,而另一个进程可以读取该文件以获取数据。 远程过程调用(Remote Procedure Call,RPC):RPC允许一个进程调用另一个进程中的函数或方法,就像调用本地函数一样。它可以在同一台计算机上的不同进程之间或在网络上的不同计算机之间进行通信。 这些方法各有优缺点,选择哪种方法取决于你的需求和特定的应用场景。 以下是一个使用C#编写的简单管道通信的示例代码: using System; using System.IO; using System.IO.Pipes; using System.Text; class Program { static void Main() { // 创建命名管道 using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut)) { Console.WriteLine("等待客户端连接..."); // 等待客户端连接 pipeServer.WaitForConnection(); Console.WriteLine("客户端已连接。"); // 从管道中读取数据 byte[] buffer = new byte[100]; int bytesRead = pipeServer.Read(buffer, 0, buffer.Length); string message = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine("从管道中读取到的数据:{0}", message); // 向管道中写入数据 string response = "Hello, pipe client!"; byte[] responseBuffer = Encoding.ASCII.GetBytes(response); pipeServer.Write(responseBuffer, 0, responseBuffer.Length); Console.WriteLine("数据已写入管道。"); // 断开连接并关闭管道 pipeServer.Disconnect(); } Console.ReadLine(); } } 这个示例代码创建了一个名为"MyPipe"的命名管道,并等待客户端连接。一旦客户端连接成功,它会从管道中读取数据,并将读取到的数据打印到控制台上。然后,它会向管道中写入一条响应消息。最后,它会断开与客户端的连接并关闭管道。 请注意,这只是一个简单的示例,实际使用管道进行进程间通信时可能需要更多的错误处理和同步机制来确保通信的可靠性和一致性。 管道通讯和Sockets通讯的区别 管道通讯和套接字(Sockets)通讯是不同的通讯机制,它们有以下区别: 连接方式:管道通讯是一种单向的通讯方式,数据在一个方向上流动,而套接字通讯是一种双向的通讯方式,数据可以在两个方向上进行流动。 通讯范围:管道通讯通常用于进程间通讯,即在同一台计算机上的不同进程之间进行通讯。套接字通讯可以用于进程间通讯,也可以用于网络通讯,即在不同计算机上的进程之间进行通讯。 通讯方式:管道通讯使用的是命名管道(Named Pipes)或匿名管道(Anonymous Pipes)来进行通讯。套接字通讯使用的是网络套接字(Network Sockets)来进行通讯。 平台支持:管道通讯在大多数操作系统上都有原生支持,包括Windows、Linux和MacOS等。套接字通讯也在大多数操作系统上有原生支持,并且可以通过不同的协议(如TCP、UDP)来实现不同的通讯方式。 数据传输方式:管道通讯是基于数据流的传输方式,数据按照顺序逐个传输。套接字通讯可以使用数据报方式(Datagrams)或流式方式(Streams)进行数据传输。 总的来说,管道通讯适用于同一台计算机上的进程间通讯,而套接字通讯既适用于进程间通讯,也适用于网络通讯。选择使用哪种通讯方式取决于你的需求和应用场景。

2025年7月24日 · 1 分钟 · 100 字

C#中异步调用函数的方法有哪些

在 C# 中,有几种方法可以进行异步调用函数: 使用 async/await 关键字:async/await 是 C# 中用于编写异步代码的关键字组合。你可以将需要异步执行的函数标记为 async,然后在其中使用 await 关键字来等待异步操作完成。这样可以使函数在异步操作执行期间不阻塞,并在操作完成后继续执行。例如: public async Task MyAsyncMethod() { // 异步操作 await Task.Delay(1000); // 异步操作完成后的代码 Console.WriteLine("异步操作完成"); } 使用 Task.Run 方法:Task.Run 方法可以将一个方法或代码块包装成一个 Task 对象,并在后台线程上执行。这样可以实现异步调用函数的效果。例如: public void MyMethod() { // 异步调用函数 Task.Run(async () => { // 异步操作 await Task.Delay(1000); // 异步操作完成后的代码 Console.WriteLine("异步操作完成"); }); // 继续执行其他代码 Console.WriteLine("异步调用进行中"); } 使用委托和回调函数:你可以定义一个异步委托,并使用回调函数来处理异步操作完成后的结果。例如: public delegate void MyAsyncDelegate(); public void MyMethod() { // 创建异步委托实例 MyAsyncDelegate asyncDelegate = new MyAsyncDelegate(MyAsyncMethod); // 异步调用委托 asyncDelegate.BeginInvoke(MyAsyncCallback, null); // 继续执行其他代码 Console.WriteLine("异步调用进行中"); } public void MyAsyncMethod() { // 异步操作 Thread.Sleep(1000); } public void MyAsyncCallback(IAsyncResult result) { // 异步操作完成后的代码 Console.WriteLine("异步操作完成"); } 这些是在 C# 中进行异步调用函数的几种常见方法。你可以根据具体的需求选择适合的方法来实现异步操作。

2025年7月24日 · 1 分钟 · 97 字

关于浏览器css&js缓存

关于浏览器css,js缓存 ctrl + F5 强制刷新 如果刷新浏览器无法清除js的缓存,就可以尝试在js文件后面加上版本号,例如:js.js?v= 在html头部加上no-cache Cache-Control Cache-Control是HTTP协议中的一个响应头部字段,用于控制缓存的行为。它指示客户端和中间缓存服务器如何缓存和重新验证响应。 Cache-Control可以包含多个指令,每个指令具有不同的含义和参数。常见的指令包括: public:表示响应可以被任何缓存(包括客户端和中间缓存服务器)缓存。 private:表示响应只能被客户端缓存,中间缓存服务器不能缓存。 no-cache:表示缓存服务器不能直接使用缓存的副本,而是需要与服务器进行重新验证。 no-store:表示不允许缓存服务器存储任何与该响应相关的内容。 max-age:表示响应的有效期,以秒为单位。缓存服务器在过期之前可以使用缓存的副本。 s-maxage:与max-age类似,但仅适用于中间缓存服务器。 使用Cache-Control可以有效地控制缓存的行为,提高网站的性能和用户体验。在C#中,可以通过设置HttpResponse的Headers属性来添加Cache-Control头部字段,例如: Response.Headers.Add("Cache-Control", "public, max-age=3600"); 上述代码将在响应中添加一个Cache-Control头部字段,指示客户端和中间缓存服务器可以缓存该响应,并将其缓存有效期设置为3600秒(1小时)。

2025年7月24日 · 1 分钟 · 21 字

glob表达式

Glob 表达式是一种用于匹配文件路径或名称的模式字符串。它在很多编程语言和操作系统中都被广泛使用,用于文件系统操作、文件搜索和筛选等场景。 Glob 表达式使用特定的通配符字符来表示匹配规则,常见的通配符包括: *:匹配任意数量的字符(包括零个字符)。 ?:匹配单个字符。 [...]:匹配方括号中指定的字符范围中的任意一个字符。例如,[abc] 匹配 a、b 或 c。 [!...]:匹配不在方括号中指定的字符范围中的任意一个字符。例如,[!abc] 匹配除了 a、b 和 c 之外的任意字符。 以下是一些示例: *.txt:匹配所有以 .txt 结尾的文件。 file?.txt:匹配 file1.txt、file2.txt 等文件,但不匹配 file.txt。 [abc]*.txt:匹配以 a、b 或 c 开头,并以 .txt 结尾的文件。 file[!0-9].txt:匹配以 file 开头,后面跟一个非数字字符,并以 .txt 结尾的文件。 需要注意的是,Glob 表达式通常是大小写敏感的,但在某些环境中可以通过设置来改变这种行为。 在 C# 中,System.IO 命名空间提供了 Directory 和 Path 类来处理文件和目录操作,可以使用 Directory.GetFiles 方法来根据 Glob 表达式获取匹配的文件路径。 总而言之,Glob 表达式是一种简单而强大的模式匹配工具,用于在文件系统中按照特定规则进行文件匹配和筛选。

2025年7月24日 · 1 分钟 · 53 字

字符编码与行尾序列

在计算机中,所有数据都是以二进制数的形式存储的,字符 char 也不例外。为了表示字符,我们需要建立一套“字符集”,规定每个字符和二进制数之间的一一对应关系。有了字符集之后,计算机就可以通过查表完成二进制数到字符的转换。 ASCII 字符集 ASCII 码是最早出现的字符集,其全称为 American Standard Code for Information Interchange(美国标准信息交换代码)。它使用 7 位二进制数(一个字节的低 7 位)表示一个字符,最多能够表示 128 个不同的字符。如图 3-6 所示,ASCII 码包括英文字母的大小写、数字 0 ~ 9、一些标点符号,以及一些控制字符(如换行符和制表符)。 然而,ASCII 码仅能够表示英文。随着计算机的全球化,诞生了一种能够表示更多语言的 EASCII 字符集。它在 ASCII 的 7 位基础上扩展到 8 位,能够表示 256 个不同的字符。 在世界范围内,陆续出现了一批适用于不同地区的 EASCII 字符集。这些字符集的前 128 个字符统一为 ASCII 码,后 128 个字符定义不同,以适应不同语言的需求。 GBK 字符集 后来人们发现,EASCII 码仍然无法满足许多语言的字符数量要求。比如汉字有近十万个,光日常使用的就有几千个。中国国家标准总局于 1980 年发布了 GB2312 字符集,其收录了 6763 个汉字,基本满足了汉字的计算机处理需要。 然而,GB2312 无法处理部分罕见字和繁体字。GBK 字符集是在 GB2312 的基础上扩展得到的,它共收录了 21886 个汉字。在 GBK 的编码方案中,ASCII 字符使用一个字节表示,汉字使用两个字节表示。 Unicode 字符集 随着计算机技术的蓬勃发展,字符集与编码标准百花齐放,而这带来了许多问题。一方面,这些字符集一般只定义了特定语言的字符,无法在多语言环境下正常工作。另一方面,同一种语言存在多种字符集标准,如果两台计算机使用的是不同的编码标准,则在信息传递时就会出现乱码。 那个时代的研究人员就在想:如果推出一个足够完整的字符集,将世界范围内的所有语言和符号都收录其中,不就可以解决跨语言环境和乱码问题了吗?在这种想法的驱动下,一个大而全的字符集 Unicode 应运而生。 Unicode 的中文名称为“统一码”,理论上能容纳 100 多万个字符。它致力于将全球范围内的字符纳入统一的字符集之中,提供一种通用的字符集来处理和显示各种语言文字,减少因为编码标准不同而产生的乱码问题。 自 1991 年发布以来,Unicode 不断扩充新的语言与字符。截至 2022 年 9 月,Unicode 已经包含 149186 个字符,包括各种语言的字符、符号甚至表情符号等。在庞大的 Unicode 字符集中,常用的字符占用 2 字节,有些生僻的字符占用 3 字节甚至 4 字节。 Unicode 是一种通用字符集,本质上是给每个字符分配一个编号(称为“码点”),但它并没有规定在计算机中如何存储这些字符码点。我们不禁会问:当多种长度的 Unicode 码点同时出现在一个文本中时,系统如何解析字符?例如给定一个长度为 2 字节的编码,系统如何确认它是一个 2 字节的字符还是两个 1 字节的字符? 对于以上问题,一种直接的解决方案是将所有字符存储为等长的编码。如图 3-7 所示,“Hello”中的每个字符占用 1 字节,“算法”中的每个字符占用 2 字节。我们可以通过高位填 0 将“Hello 算法”中的所有字符都编码为 2 字节长度。这样系统就可以每隔 2 字节解析一个字符,恢复这个短语的内容了。 ...

2025年7月24日 · 2 分钟 · 229 字

分布式锁

分布式锁是一种用于在分布式系统中实现并发控制的机制。在分布式系统中,多个节点同时访问共享资源可能导致数据不一致或冲突的问题。分布式锁可以确保在任意时刻只有一个节点可以访问共享资源,从而避免并发冲突。 分布式锁通常使用的是互斥锁(Mutex)的概念,它可以保证在同一时刻只有一个节点能够获取到锁,其他节点需要等待。一旦一个节点获取到了分布式锁,它就可以执行需要保护的临界区代码,执行完成后释放锁,其他节点才能继续竞争获取锁。 实现分布式锁的方式有很多种,常见的方式包括使用数据库、缓存系统(如Redis)、分布式协调服务(如ZooKeeper)等。这些方式都提供了原子操作和分布式特性,可以确保在分布式环境下实现可靠的锁机制。 使用分布式锁可以解决分布式系统中的并发控制问题,确保共享资源的安全访问,提高系统的可靠性和性能。然而,分布式锁的设计和实现需要考虑到各种复杂的情况,如死锁、锁竞争、性能等,因此在使用时需要仔细考虑和评估。 ps rm -rf /* 是一个具有破坏性的命令,它在Unix和类Unix系统中用于删除文件和目录。这个命令的含义是递归地删除根目录下的所有文件和目录,包括系统关键文件和目录。由于这个命令的执行效果非常危险且不可逆,因此不推荐在生产环境或正常操作中使用。 rm 是一个用于删除文件和目录的命令,-rf 是rm命令的选项,其中 -r 表示递归删除目录及其内容,-f 表示强制删除,不进行确认提示。 如果在终端中执行 rm -rf /* 命令,它会立即删除根目录下的所有文件和目录,包括系统关键文件和目录,这将导致系统无法正常运行,数据丢失以及系统崩溃。因此,请务必小心使用该命令,并确保仅在了解其后果并且有充分的理由时使用。

2025年7月24日 · 1 分钟 · 20 字