.NET 窗体应用中的多线程误区~~

这两天考虑做一个中间处理等待画面,   意图在处理复杂过程时弹出待用 不断滚动  (子窗体同时被不断更新的)的滚动条的子窗体,  在处理完毕之后关闭它。

设想是实现 Form1 能像如下方法进行调用:

Private   Sub  Button1_Click( ByVal  sender  As  System.Object,  ByVal  e  As  System.EventArgs)  Handles  Button1.Click
        
Dim  frm1  As  Form1  =   New  Form1
        ' 显示
等待窗体。
        frm1.Show()
       
'  复杂的处理过程。
        Thread.Sleep(5000)
      
' 关闭等待窗体。
        frm1.Close()
End Sub


Form1 添加了一个 ProgressBar 控件:

Private   Sub  Form1_Load( ByVal  sender  As  System.Object,  ByVal  e  As  System.EventArgs)  Handles   MyBase .Load
        
Me .ProgressBar1.MarqueeAnimationSpeed  =   300
        
Me .ProgressBar1.Style  =  ProgressBarStyle.Marquee
End Sub


但实际上,这并不是我想要的效果。 Form1 被 Show 出来了,可是 Form1 好像假死一样无法动弹, 更糟糕的是滚动条都没有正常显示。(csdn的图片上传怎么还没有弄好啊。。。)

心想是不是 Form1 没有被 Load 完就 Show 出来了呢? 于是搬来了  Application.DoEvents()

Private   Sub  Button1_Click( ByVal  sender  As  System.Object,  ByVal  e  As  System.EventArgs)  Handles  Button1.Click
        
Dim  frm1  As  Form1  =   New  Form1
        frm1.Show()
        Application.DoEvents()
       
'  复杂的处理过程。
        Thread.Sleep(5000)

        frm1.Close()
End Sub


Application.DoEvents()  使得处理完所有的窗体消息队列中的所有消息之后,再处理复杂的过程。效果改进了T_T
现在滚动条能显示出来了,但是依然动弹不能。。。

还以为是因为复杂的处理阻塞了通在一个主线程里的 Form1 里的刷新处理。于是把 Form1 扔到子线程里去。

Dim  frm1  As  Form1  =   New  Form1
myThread 
=   New  Thread( New  ThreadStart( AddressOf  frm1.Show))
myThread.Start()
Application.DoEvents()
'  复杂的处理过程。
Thread.Sleep(5000)

结果让人惊讶, Form1 在启动后立即消失了。查了一下msdn: http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/misMultithreading.mspx?mfr=true

WinForm中负责响应用户输入和保持用户界面为最新的线程(通常称为 UI 线程)。所以上面的代码中 Thread.Sleep(5000) 放在了 Button_Click 的处理方法中。 这样实际是阻塞了 UI线程, 无论使用哪种多线程都无法实现对 Form1 的异步刷新, 解决办法只能是将 Button_Click 中的复杂处理移出 UI 线程。。。

Public   Class Form2

    
Private myThread As Thread
    
Private frm1 As Form1 = Nothing

    
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ProgressBegin()
        
Dim mi As MethodInvoker = New MethodInvoker(AddressOf Me.DoSomething)
        mi.BeginInvoke(
NothingNothing)
    
End Sub


    
Public Sub DoSomething()
        Thread.Sleep(
5000)
        
If frm1 IsNot Nothing Then
            
Dim mi As MethodInvoker = New MethodInvoker(AddressOf Me.ProgressEnd)
            
Me.Invoke(mi)
        
End If
    
End Sub


    
Private Sub ProgressBegin()
        
Me.Label1.Text = ""
        frm1 
= New Form1()
        frm1.Show()
        
Me.Enabled = False
        My.Application.DoEvents()
    
End Sub


    
Private Sub ProgressEnd()
        
If frm1 IsNot Nothing Then
            frm1.Close()
            
Me.Label1.Text = "over."
            
Me.Enabled = True
            
Me.Focus()
        
End If
    
End Sub


End Class

你可能感兴趣的:(.NET 窗体应用中的多线程误区~~)