了解“Windows窗体应用程序”项目中Program.cs文件中的main方法与传统C Console控制台程序中的main方法的区别,等等。感兴趣的朋友可以了解一下。
1.了解“Windows窗体应用程序”项目中Program.cs文件中的main方法与传统C Console控制台程序中的main方法的区别。从程序操作的层面来说,两者没有区别。它们是程序的入口点,属于进程中的第一个线程。前者隐藏了UI应用程序所必需的消息循环,而后者没有。
2.每个Windows桌面应用程序必须包含至少一个UI线程。所谓UI线程,就是可以响应Windows消息的线程。通常,除非另有要求,否则Windows桌面应用程序只包含一个UI线程。
3.UI线程本质上和普通线程一样,一般是程序的入口线程。例如,Program.cs文件中的主方法是UI线程,而应用程序。Run()方法封装了消息循环。如果没有申请。Run()方法,那么它和其他线程完全一样。之所以叫UI线程,是因为它包含了一段类似于复制代码的代码如下:While(GetMessage(…))//Get Windows message {//process Windows message,调用开发人员编写的回调方法,比如事件处理程序等。}的循环。4.关于Windows消息机制的信息,请上网去Google或者百度。
5.UI线程主要负责界面的实时更新,所以开发者在编写代码时,请遵循以下规则:1)不要在控件的事件处理程序中编写(或调用)耗时的代码块;2)不要在控件的事件处理程序中调用blocking方法;
6.理解委托、事件和事件处理程序在编程中的区别。复制代码如下:1)公共委托Void Keypress EventHandler(Keypress EventHandler);2)Public event KeyPress eventhandler按键;3)public void textbox 1 _ key press(object sender,key press eventargs e){/…}其中:1是委托2是事件3是事件处理程序。
7.所有的事件处理程序都是在UI线程中调用的,而且由于UI线程负责更新接口,所以UI线程必须一直保持流畅(3中的while循环不能用太长时间),也就是不能出现一个方法执行了很久没有返回的情况。所以,请遵守5中的规则。
8.相同的方法可以在多个线程中运行。方法和线程之间没有一对一的原则。复制代码如下:PrivateVoidThread _ Pro()/{ } 1)private button 1 _ Click(对象发送方,eventargs e){ thread _ Pro();//thread_pro在UI中运行thread} 2) privatebutton1 _ click(对象发送方,eventargs e){ thread t=new thread(new threadstart(thread _ pro));Thread t1=新线程(new ThreadStart(Thread _ pro));thread T2=new thread(new ThreadStart(thread _ pro));t . start();//thread_pro运行在t线程t1.start()中;//thread_pro运行在t1线程t . 2 . start();//thread_pro运行在t2线程中}
3)也可以通过控件将方法发布到创建控件的线程。调用()或BenginInvoke方法来执行。在上述所有情况下,请注意线程共享数据。
9.多线程编程中,请注意“线程安全”的问题。对于一些具有“非原子”操作的对象,必须采取措施来避免错误。
UI(按钮、datagridview等。)、集合(List、ArrayList)等。属于这种对象,控件不能随时被多线程访问。
10.坚决杜绝跨线程访问UI控件。原因见9。有关跨线程访问控件的方法,请参见8中的3)。
11.除了。Net Winform是在UI线程中调用的,几乎所有其他回调方法都不会在UI线程中执行。因此,开发人员在编写回调方法时,应该遵守第9条和第10条规则。
12.理解什么是回调方法。回调一般是开发者写的,但不是开发者调用的,而是系统(或者框架)调用的。在Windows桌面应用程序的开发过程中,控件的事件处理程序属于回调方法,一般在“观察者”设计模式中使用。当事件的发起者触发事件时,它将调用回调方法。控件的所有事件都属于这个类。另一种常见的方式是异步执行操作,比如socket中的AsyncCallBack类型参数。BeginAccept()。在框架横行的时代,一般开发者写的代码都属于回调代码。因为程序的主体结构已经被老祖宗整合在框架里了。开发者只需要像填空一样完善空缺的部分。
13.阻塞方法意味着方法不能及时返回,因为方法体包含耗时的操作。“及时”和“不及时”之间没有绝对的界限。例子如下:Copy code代码如下:int func1() //及时返回{ Int index=0;for(int I=0;i100i ) {索引;}回报指数;} Int func2() //未及时返回{ Int index=0;for(int I=0;i1000I){ For(int j=0;j1000j){ Index;} }回报指数;}相对来说,上面的func1是非阻塞方法,而func2是阻塞方法。
14.Windows窗体应用程序不直接与键盘和鼠标等硬件设备交互,而只与Windows消息交互。虽然鼠标键盘等硬件设备表面上是对表单进行操作,但实际上你写的桌面应用并不会了解这些硬件设备的一举一动。它们由操作系统(驱动程序)桥接。操作系统先把硬件设备的一举一动翻译成windows消息(程序能理解的数据结构),然后程序才能理解并做出相应的响应。15.所谓“阻塞调用线程”,就是在某个线程中调用阻塞方法,使该线程不能及时执行后面的代码。复制代码如下:Void func(){ Int index=0;for(int I=0;i10000I){ For(int j=0;j10000j){ I index;} } } Thread t=new Thread(new ThreadStart(func));t . Start();//线程T中调用了阻塞方法func,所以线程T会被阻塞。在介绍func方法时,可以这样描述:这个方法会阻塞调用线程。
16.同一个方法可以被多个线程调用,包括UI线程和非UI线程。那么如何在方法体中编写访问UI控件(UI元素)的代码呢?(跨线程访问UI控件会引发异常。)复制代码如下:Void func() {Textbox1。Text=" test图片框1。图像=图像。from file(" a . jpg ");} 1)上述func方法可能在UI线程中运行,如下:复制代码如下:Private void button 1 _ click(object sender,eventargs e){ func();//调用func方法} 2)有以下几种。func方法可以在其他非UI线程中运行。复制代码代码如下:Private Voidbutton1 _ click(对象发送方,eventargs e){ thread t=new thread(new threadstart(func));t . Start();//func access在2)中的T thread}中运行,可能会抛出异常。解决上述问题的方法是:将func代码修改为:复制代码如下:func () {if (this.invoke必选){ this . begininvoke((action)delegate(){ func()});} Else {Textbox1。Text=" test图片框1。图像=图像。from file(" a . jpg ");}}关于BeginInvoke或Invoke方法的使用,请上网Google或百度。
17.“跨线程访问UI控件可能导致异常”的原因和多线程访问集合可能导致错误的原因基本相似。下面列出的代码解释了这种情况。复制代码如下:ClassMyControl { Object rootpublic Draw(){ GetRoot(root);//一系列操作…release root(root);} Public other draw(){ GetRoot(root);//一系列操作…release root(root);}}在根变量在同一时间只能被占用一次的情况下,GetRoot()获得Root的访问权限,如果root已经被占用则抛出异常。ReleaseRoot()释放根占用。
当一个线程(比如UI线程)访问MyControl类对象A,调用A.Draw()方法,执行GetRoot(root)方法时,线程失去控制,挂起正在运行的代码,也就是此时根被占用。但是,如果另一个线程也想访问同一个对象A的Draw()方法,就会抛出异常。
18.英寸Net Winform应用程序,程序与用户的交互主要包括两个方面。首先,用户用鼠标和键盘灯操作,程序响应操作,然后给出反馈(比如更新界面,刷新数据等。);二、程序自动反馈(如QQ弹窗新闻表单和360弹窗等。)而无需用户用鼠标和其他硬件设备操作。
第一种情况是我们所熟知的。例如,当用户用鼠标点击按钮(button1)时,程序会弹出一个消息框。我们在程序中是这样写的:事件处理程序复制代码如下:Private void button 1 _ click(object sender,eventargs e) {messagebox.show("弹出对话框,或其他操作");}我们再来管理一下这个过程。首先,用户拿起鼠标单击button1,操作系统(鼠标驱动程序)将捕获这个事件。经过分析,操作系统知道用户点击了哪个表单(按钮)、点击位置(坐标)、点击类型(左键或右键或其他)以及其他信息。之后,它将这些信息封装成一个类型(即windows message)并发送给窗体(控件)然后,UI线程从线程消息队列中获取消息(注意:这个过程一直存在),分析消息,调用一些开发者编写的回调方法,比如button1_Click()方法,从而达到相应的鼠标键盘操作的目的。从上面的分析过程来看,还是那句话,程序不会直接和鼠标等硬件设备进行交互,只会和Windows消息进行直接交互,而这个过程需要Windows操作系统发挥重要作用。
第二种情况一般用在多线程编程中。当程序有耗时的操作或者需要一直监控时,就不能放在UI线程中。这时候就需要打开另一个线程,在另一个线程中处理。在这种情况下,其他线程有时需要向用户反馈一些信息,即更新UI界面或弹出表单等。这涉及到跨线程访问UI元素的问题。详见5、5。
19.以上代码部分是现在写的,可能会出现拼写错误。不好意思!另外,请结合注(2)中的“DOT NETWinform应用程序运行结构图”阅读。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。