WinForm 的线程问题!!!200分!求解答.....
搞了大半天,我还是不懂WinForm的线程原理!!其实,到底它的原理是怎么样的?是每当它New 一个窗体,然后再把它Show(),它就会自动新建一个线程的吗?当这个窗体向服务器发送一个请求,又或者用delegate方法从服务器接收数据也都会自动建一个线程的吗?
前些天我想把一个项目的所有模块功能都整合到一个WinForm 主界面上,但是在主界面调用到其它模块的窗体时,遇到了很多问题。我用ShowDialog()方法调用一个窗体的时候,遇到一个DragDrop注册失败的问题,百度过后,试了很多方法,
Thread t = new Thread(new ThreadStart(delegate() { StaticObject.myFRMRenYuanJiChu.ShowDialog(); }));//新建一个线程
t.ApartmentState = ApartmentState.STA;//加上这句话!
t.Start();//开始线程
上面这个才终于暂时解决了这个问题。但是在调用刚才窗体用到TCPClients向Server端发送请求的时候,
StaticObject.myclient.Send(DGVPIC, (TCPClients.DataTypeList)DataType.FRMRenYuanJiChu_SelectRenYuanFlag);
请求根本发送不过去了,Server端没反应!!这个也是因为线程问题吗?
应该很多大神有遇到过类似的问题吧!!!求教!!!
------解决方案--------------------说说自己的见解:
1.new一个新的窗体Form1,那么Form1就会有一个线程Thread1,Thread1就是控件的线程,也就是说你可以在这个线程中操作控件。
2.假设你又在Form1这个线程上new了一个新的线程Thread2,那么Thread2就是一个独立的线程,这个时候Thread2不能操作Form1中的控件,因为这些控件是属于Thread1的。
至于delegate,我是这么理解的,Thread1想从服务器接收信号,但是接收信号的功能Thread1不想自己实现,正好Thread2有一个这个方法,OK 那就委托给你做了。
------解决方案--------------------WinForm的内部实现采用了操作系统的Window。而Window的核心机制就是他的消息循环(也叫消息泵)。
每个Window UI线程,都拥有一个消息队列。其他线程(或者自己,或者其他进程)可以给他发消息。这时,消息添加到消息队列中去。
消息泵,就是用来处理该消息队列的一个循环:
while(GetMessage(out msg))
{
ProcessMessage(msg);
}
如果GetMessage取出的消息,是关于鼠标点击,那ProcessMessage可能触发button.OnClick。
如果GetMessage取出的消息,是定时器消息,那ProcessMessage可能触发timer.OnTick。
因此button.OnClick和timer.OnTick都是在一个循环里面发生的,它们都运行在
同一个线程下,即拥有该消息泵的UI线程。所以WinForm的控件消息处理没有同步的困扰。
在早期的OLE(Object Linking and Embedding)开发中,为了简化线程模型,一种方式就是广泛使用Single Thread Apartment(也就是那个ApartmentState.STA)。这种方式下,利用了消息泵没有同步困扰的有点,把OLE的回调,通过Windows消息来实现。
而剪贴板,拖放(DragDrop)等OLE操作,就是采用简单的STA模式。因此.Net要求当前的线程的AppartmentState必须是STA。
至于.Net的TcpClient,他没有线程相关性。你的问题(不能发送)不是TcpClient本身的问题。
------解决方案--------------------没看懂你想要如何来实验。
说说我自己的见解:
一个程序的进程中,可以有多个线程。
你刚建立的默认的winform工程所在的线程是主线程。如果你在主线程里面创建任何的form这些form的资源都是属于主线程的。
也就是说任何的控件,在某个线程中被创建,那么这个控件的资源就属于这个线程。
你想实现的估计就是几个form并存,并且都不会互相干涉,比如有2个form,form a和form b,a和b同时显示,但是a不会挡住不让b操作,b同样。
form有两种show的方式,show和showdialog,show就是非模式窗体,这种窗体不会挡住其他窗体的操作。showdialog是模式窗体,也就是说这种窗体一旦被show出来,除非关闭其他的窗体是无法操作的。
另外你想跨线程传值,这个东西真要具体情况具体分析了,一下说不清楚