目录

  • 委托的使用
    • 委托的概念,简单匿名函数与lamda表达式使用
    • 委托的定义与使用
    • 多播委托
    • 泛型委托
      • 匿名方法
      • Lamda表达式
    • 举例
  • 扩展方法
  • winform间窗体传值
    • 传统方法
    • 使用委托
    • 事件方式实现
    • 发布订阅模式的实现
  • 文件流复习
    • 选择文件并读取
    • 写入文件
  • 多线程
  • WinFrm与多线程
    • 跨线程访问控件
  • 进程与线程

委托的使用

委托的概念,简单匿名函数与lamda表达式使用

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用语句,同时使得程序具有更好的可扩展性。
把一个方法作为参数传给另一个方法
委托内部由三部分:1,_methodPtr,是一个方法指针,指向当前委托指向的方法的内存地址;
2,_target,目标对象,如下

Program p=new Program();
del += p.AddStaticFunc1;

中,方法指针指向的是AddStaticFunc1方法,目标对象就是p
3、委托链,就是一个委托数组,定义委托实例AddDel del = new AddDel(AddStaticFunc);的背后就是创建这三个部分,当指向的方法为静态方法的时候,_target为null。
执行的时候,从委托链的第0个索引到最后一个索引,因此多播委托返回的是最后一个方法的执行结果。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 委托概念
{internal class Program{//声明一个委托指向一个函数//委托指向的参数必须跟委托具有相同的签名public delegate void DelSayHi(string name);static void Main(string[] args){//DelSayHi del = English;//new DelSayHi(English);//del("张三");//test("张三",Chinese);//test("李四", English);/*DelSayHi del=delegate (string s){Console.WriteLine("中文" + s);};*/DelSayHi del = (string s)=>{Console.WriteLine("中文" + s);};//lamda表达式,匿名函数的简写形式 => goes todel("张三");Console.ReadKey();}public static void test(string name, DelSayHi del){del(name);}public static void Chinese(string name){Console.WriteLine("中文"+name);}public static void English(string name){Console.WriteLine("英文" + name);}}
}

委托的定义与使用

委托的定义与使用:
代码1:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApp1
{//定义一个委托类型delegate int AddDel(int a, int b);internal class Program{static void Main(string[] args){//定义一个委托的实例AddDel del = new AddDel(AddStaticFunc);//触发实例int r = del(3, 4);Console.WriteLine(r);Console.ReadKey();}//定义一个符合委托规范的方法public static int AddStaticFunc(int a,int b){return a + b;}}
}

结果输出:7
代码2:
匿名函数使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 委托
{internal class Program{public delegate string DelProStr(string name);static void Main(string[] args){// ProStrSYH(names);string[] names = { "abcdEFG", "HIjklMn" };ProStr(names, delegate(string name){return name.ToUpper();});//匿名函数,用delegate代替,只执行一次用for (int i = 0; i < names.Length; i++){Console.WriteLine(names[i]);}Console.ReadKey();}public static void ProStr(string[] name,DelProStr del){for (int i = 0; i < name.Length; i++){name[i] = del(name[i]);}}/* public static string StrToUpper(string n){return n.ToUpper();}public static string StrToLower(string n){return n.ToLower();}public static string StrSYH(string name){return "\"" + name + "\"";}*//* public static void ProStrToUpper(string[] name){for(int i = 0; i < name.Length; i++){name[i] = name[i].ToUpper();}}public static void ProStrToLower(string[] name){for (int i = 0; i < name.Length; i++){name[i] = name[i].ToLower();}}public static void ProStrSYH(string[] name){for (int i = 0; i < name.Length; i++){name[i] = "\"" + name[i]+ "\"";}}*/}
}

输出:
ABCDEFG
HIJKLMN

多播委托

多播委托1:

Program p=new Program();
del += p.AddStaticFunc1;
public int AddStaticFunc1(int a, int b)
{return a + b+1;
}

执行结果:8
使用多播委托时,拿到的委托返回值是最后一个委托指向的方法的执行结果。
多播委托2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 委托
{//可以指向多个函数public delegate void DelTest();internal class Program{static void Main(string[] args){DelTest del = T1;del += T2;del -= T1;del();Console.ReadKey();}public static void T1(){Console.WriteLine("T1");}public static void T2(){Console.WriteLine("T2");}public static void T3(){Console.WriteLine("T3");}public static void T4(){Console.WriteLine("T4");}}
}

执行结果:T2 T3 T4

泛型委托

简单例子:

Func<int, int,int> funcDemo = new Func<int, int,int>(AddStaticFunc);
int result=funcDemo(1,2);
Console.WriteLine(result);
public static int AddStaticFunc(int a,int b)
{return a + b;
}

结果是3。
Func原构造函数:

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

可以有很多个int,但是要有一个out,最后一项是用来约束返回值的。

匿名方法

Func<int, int,int> funcDemo = delegate(int a,int b) { return a + b; };

Lamda表达式

Func<int, int,int> funcDemo = (int a,int b)=> { return a + b; };
或
Func<int, int,int> funcDemo = (int a,int b)=>  a + b;

例子:

public delegate void DelOne();
public delegate void DelTwo(string name);
public delegate string DelThree(string name);
static void Main(string[] args)
{//DelOne del = delegate () { };DelOne del = () => { };//DelTwo del2 = delegate(string name) { };DelTwo del2 = (string name) =>{};/*DelThree del3 = (string name) =>{return name;};*/DelThree del3 = delegate (string name){return name;};List<int> list=new List<int> { 1, 2, 3 };list.RemoveAll(n => n > 4);//lamda表达式
}

举例

List<string> list = new List<string>()
{"3","9","32","7","2"
};
var temp = list.Where(delegate (string a)
{return a.CompareTo("6") < 0;
});
foreach (var v in temp)
{Console.WriteLine(v);
}
Console.ReadKey();

where是扩展方法,内部会遍历list集合,把每个元素传到委托里执行,如果返回true,就把元素选择出来,最后把所有满足条件的元素一起返回

扩展方法

三要素:静态类、静态方法、this关键字
重新定义where方法
定义:

public static class Class1
{public static List<T> myWhere<T>(this List<T> list,Func<T,bool> funcWhere){List<T> result = new List<T>();foreach (var item in list){if (funcWhere(item)){//调用委托,如果满足条件,加到集合中result.Add(item);}}return result;}
}

调用:

List<string> list = new List<string>(){ "3","9","32","7","2"};
匿名方法:
var temp = list.myWhere(delegate (string a)
{return a.CompareTo("6") < 0;
});
lamda表达式var temp = list.myWhere<string>(a => a.CompareTo("6") < 0);
方法泛型的约束可以省略,但是如果是显式的约束就必须满足约束。
即<string>可以省略不写,就像var demo = "sss";一样,编译器会自动推断类型
foreach (var v in temp)
{Console.WriteLine(v);
}
Console.ReadKey();

winform间窗体传值

传统方法

form1和form2两个类之间传值,在from1定义一个form2的对象,并将form2中文本框设置为外部可访问,如下所示。
form1:

public Form2 myForm2 { get; set; }
private void button2_Click(object sender, EventArgs e)
{myForm2.textBox2.Text = this.textBox1.Text;
}

form2的designer中:

public System.Windows.Forms.TextBox textBox2;

但是,对象内部的字段或者元素最好不要直接让外部访问,最好通过设置的方法控制一下。
例如,设置为私有后,在子窗体定义函数,父窗体中的子窗体对象调用函数:

public void SetText(string txt)
{textBox2.Text = txt;
}
myForm2.SetText(this.textBox1.Text);

使用委托

主窗体发送消息:点击按钮执行委托,给委托传递参数(当前文本框的内容),子窗体想接收就注册主窗体的委托,把子窗体的方法注册到委托中,执行时,委托执行每个子窗体的方法
主窗体发布,子窗体订阅
主窗体:点击按钮,执行委托

public Action<string> AfterMsgSend { get; set; }
public Form2 myForm2 { get; set; }
private void button2_Click(object sender, EventArgs e)
{if(AfterMsgSend == null){return;}AfterMsgSend(this.textBox1.Text);
}
private void Form1_Load(object sender, EventArgs e)
{Form2 frm = new Form2();myForm2 = frm;//关注主窗体消息的变化AfterMsgSend+= frm.SetText;frm.Show();
}

SetText是Form2的一个方法

public void SetText(string txt)
{textBox2.Text = txt;
}

事件方式实现

//定义消息发布的事件
public event EventHandler AfterMsgEvent;
//EventHandler 是最常见的事件委托类型,子窗体需要符合它的规范
事件触发:
private void button2_Click(object sender, EventArgs e)
{AfterMsgEvent(this, new TextChangeEvent(){Text = this.textBox1.Text});
}
TextChangeEvent是一个类,继承事件,含有属性Text
public class TextChangeEvent:EventArgs
{public string Text { get; set; }
}
//加载父窗体时的事件
AfterMsgEvent += frm.AfterParentFrmChange;
Form2中函数:
public void AfterParentFrmChange(object sender, EventArgs e)
{//拿到父窗体传过来的值TextChangeEvent text=e as TextChangeEvent;this.SetText(text.Text);
}

**区别:**委托是类型,事件是委托类型的一个特殊实例,事件只能在类的内部触发执行,安全

发布订阅模式的实现

发布订阅模式
观察者模式
指的是一个
发布订阅:子窗体的个数和类型对主窗体没有影响
如果不使用委托,在主窗体点击按钮,遍历集合,集合存放所有关心此主窗体消息变化的所有子窗体,这个集合相当于注册委托或事件方法
定义一个接口类型:

public interface Interface1
{void SetText(string text);
}

子窗体:

public partial class ChildFrm : Form,Interface1
{//继承基类,实现接口public ChildFrm(){InitializeComponent();}public void SetText(string text){//实现接口的方法this.textBox1.Text = text;}
}

父窗体:

public partial class ParentFrm : Form
{public List<Interface1> ChildFrmList { get; set; }public ParentFrm(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){//遍历所有关注主窗体消息变化的子窗体集合//调用集合中每个元素的方法if(ChildFrmList==null) return;//减少括号的层次,比先判断不是空再循环要好一些foreach(var item in ChildFrmList){item.SetText(this.textBox1.Text);}}private void ParentFrm_Load(object sender, EventArgs e){ChildFrm frm=new ChildFrm();this.ChildFrmList=new List<Interface1>();this.ChildFrmList.Add(frm);frm.Show();}
}

如果再多加一个管理窗体,加载时的执行代码为:

//弹出主窗体
ParentFrm parentForm = new ParentFrm();
parentForm.Show();
ChildFrm childForm = new ChildFrm();
parentForm.ChildFrmList = new List<Interface1>();
parentForm.ChildFrmList.Add(childForm);
childForm.Show();

这样,就实现了主窗体和子窗体的分离解耦。

文件流复习

选择文件并读取

using(OpenFileDialog ofd=new OpenFileDialog())
{if(ofd.ShowDialog() != DialogResult.OK){return;}//选中文件后,读取文件//1、//string x=File.ReadAllText(ofd.FileName, Encoding.Default);//直接写,如果文件太大会卡死//2、使用文件流using(FileStream fs=new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read)){textBox1.Text = ofd.FileName;using(StreamReader sr=new StreamReader(fs)){while (!sr.EndOfStream){string line=sr.ReadLine();this.textBox2.Text += line;}}}
}

写入文件

using(SaveFileDialog save=new SaveFileDialog())
{if(save.ShowDialog() != DialogResult.OK){return;}//1、//File.WriteAllText(save.FileName,textBox2.Text,Encoding.Default);//2、/*using(StreamWriter sw=new StreamWriter(save.FileName,false,Encoding.Default,1024*1024)){//第二个参数是是否追加的意思,最后一个参数为缓冲区大小sw.Write(textBox2.Text);sw.Flush();//一举写入}*///3、文件流写入using(FileStream fs=new FileStream(save.FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)){string x=textBox2.Text.Replace("\n","\r\n");byte[]data=Encoding.Default.GetBytes(x);//不读取换行,一行行的读写,因为x没有\r//fs.Write(data,0,data.Length);}
}

多线程

一个线程就是一个进程里的代码执行流,每个线程都要指向一个方法体,方法执行完成之后,线程就释放。
例如:

Thread thread = new Thread
(delegate ()
{Console.WriteLine(DateTime.Now);Thread.Sleep(1000);
});
相当于
Thread thread = new Thread(ThreadMethod);
static void ThreadMethod()
{Console.WriteLine(DateTime.Now);Thread.Sleep(1000);
}

进程执行是调用Start()方法,线程默认是前台线程。尽量设置为true

thread.IsBackground = true;
thread.Start();

进程退出的标志:所有的前台线程都结束之后,后台线程不会阻塞进程的退出。
程序执行时,Main函数是程序的入口,CLR一开始就默认创建一个主线程,主线程也是一个前台线程。

Thread thread = new Thread(ThreadMethod);
thread.IsBackground = true;
thread.Start();
while (true)
{Console.WriteLine("from 主线程-----");Thread.Sleep(1000);
}
Console.ReadKey();

执行结果:

主线程与创建的线程不停的执行,类似于俩个线程同时在执行。
线程的其它属性:1、 IsAlive表示当前线程的状态,2、ManagedThreadId表示线程id
如下:

Console.WriteLine(thread.ManagedThreadId);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

3、优先级
设置为最高都是建议操作系统设置为最高,不一定为最高;线程执行是告诉操作系统可以执行,自己准备好了。

thread.Priority = ThreadPriority.Highest;

4、挂起:thread.Suspend();
5、继续挂起的线程:thread.Resume();
6、终止Abort,不得已才能用,直接终结:thread.Abort();
7、等待thread线程执行完成:thread.Join();,执行代码的线程等待thread执行完成,参数为超时时间。
例如:thread.Join(5000);后的代码执行结果为:

WinFrm与多线程

创建一个Windows窗体,设置为控制台输出

如果不使用线程,显示窗体线程就是前台线程,卡死;
如果设置了线程,使用lamda表达式输出内容,设置为前台线程,既可以控制台输出,主窗体也不卡死,关掉窗体,线程关闭。
如果不设置线程为前台线程,那么关闭主窗体,控制台仍然执行。

Thread thread = new Thread(() =>
{while(true)Console.WriteLine(DateTime.Now.ToString());
});
thread.IsBackground = true;
thread.Start();

跨线程访问控件

线程访问主线程(主窗体)控件,设置非法跨线程为false;但是这个属性只是演示,真正项目不可以使用。

Control.CheckForIllegalCrossThreadCalls = false;

正确访问方法:

Thread thread = new Thread(() =>
{if (button1.InvokeRequired){//检查是否为别的线程创建的子控件,为true//找到创建控件的线程,执行方法button1.Invoke(new Action<string>(s => {this.button1.Text = s;}), DateTime.Now.ToString());}else   this.button1.Text = DateTime.Now.ToString();while(true)Console.WriteLine(DateTime.Now.ToString());
});
thread.IsBackground = true;
thread.Start();

进程与线程

操作系统分配的资源最小单位是进程,进程与进程之间互不影响,可以理解为一个程序的基本边界。
进程是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。进程之间是相对独立的,一个进程无法直接访问另 一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域 的。进程可以理解为一个程序的基本边界。
CPU的其中一个核心,同一时间只能执行一个指令。
一个线程就是一个进程里面的代码的执行流。每个线程都要指向一个方法体,方法执行完成后线程就释放。
输出所有进程:

var allPro = Process.GetProcesses();
foreach (var pro in allPro)
{Console.WriteLine(pro.ProcessName + "\t" + pro.Id);
}

打开某个进程:

Process.Start("notepad", "aaa.txt");

第二个参数是文件名,如果打开浏览器,是网站地址

多线程(一)——委托与多线程相关推荐

  1. 异步委托实现多线程winform控件编程

            private void button1_Click(object sender, EventArgs e)         {             ThreadStart ts  ...

  2. BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题

    BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题 参考文章: (1)BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题 (2)https://www. ...

  3. C# Delegate(委托)与多线程

    C# Delegate(委托)与多线程 很多时候写windows程序都需要结合多线程,在.net中用如下得代码来创建并启动一个新的线程.     public void ThreadProc();   ...

  4. C# 多线程 与 委托

    简单的多线程: protected void Page_Load(object sender, EventArgs e){ParameterizedThreadStart _Parameterized ...

  5. [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)...

    [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...

  6. python多线程没用_python的多线程到底有没有用?

    在群里经常听到这样的争执,有人是虚心请教问题,有人就大放厥词因为这个说python辣鸡.而争论的核心无非就是,python的多线程在同一时刻只会有一条线程跑在CPU里面,其他线程都在睡觉.这是真的吗? ...

  7. 异步多线程(五)多线程异常处理

    异步多线程(五)多线程异常处理 参考文章: (1)异步多线程(五)多线程异常处理 (2)https://www.cnblogs.com/JohnTang/p/11010357.html (3)http ...

  8. python多线程爬虫实例-Python多线程在爬虫中的应用

    题记:作为测试工程师经常需要解决测试数据来源的问题,解决思路无非是三种:(1)直接从生产环境拷贝真实数据 (2)从互联网上爬取数据 (3)自己用脚本或者工具造数据.前段时间,为了获取更多的测试数据,笔 ...

  9. python多线程爬虫实例-Python3多线程爬虫实例讲解代码

    多线程概述 多线程使得程序内部可以分出多个线程来做多件事情,充分利用CPU空闲时间,提升处理效率.python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点, ...

  10. python多线程的作用_Python多线程中三个函数的强大功能简介

    在Python多线程中有三个比较简单的函数,在实际的相关操作中你对这一实际操作是否了解?是否对其感兴趣?如果你想对Python多线程的开发与多线程程序及相关实际操作方案有所了解的话,你就可以点击以下的 ...

最新文章

  1. QT 5.4.1 for Android Ubuntu QtWebView Demo
  2. docker java 不兼容_Apple M1 芯片不支持 Docker?Docker:正在努力适配
  3. 虚幻4 Object和序列化
  4. 程序员打产品经理事件:做不了的事情,直接推给主管
  5. 最新基于高德地图的android进阶开发(3)GPS地图定位
  6. C语言程序设计的课程目标,《C语言程序设计》课程标准
  7. UCHome二次开发 规范
  8. Redis和消息队列
  9. QM 、QA和QC的区别
  10. 最优停止找停车位问题的最简单解释
  11. 自动爬取微博热门评论和点赞数并存为EXCEL文件(python2)
  12. 习题6-5 巡逻机器人(Patrol Robot, ACM/ICPC Hanoi 2006, UVa1600)
  13. Web Editor插件 网页在线编辑器
  14. HiAGM模型源码测试【原始数据集+中文数据集】
  15. Android Vitamio
  16. 解决ios在微信内置浏览器中video播放的全屏问题
  17. 2023软著申请,办理进度分享
  18. Chrome 的7大缺陷以及相关解决方案
  19. 开关电源(DC-DC)与LDO电源的区别---纹波
  20. ABAQUS盾构隧道穿越既有隧道和铁路数值模拟模型,有源文件

热门文章

  1. Win7 的70个使用技巧
  2. 案例驱动式Python学习笔记【第三篇】居民身份证信息提取
  3. Java并发编程-Exchange
  4. lnmp下nginx出现5xx问题解决汇总
  5. 仿京东图片放大镜动效
  6. 二维空间下的向量旋转
  7. 20.2 Java写文件之OutputStream学习
  8. 05Linux 第2天 进阶指令
  9. 简单3步将你的python转成exe格式
  10. 审稿审什么你真的弄清楚了吗