Visual Basic,子线程阻塞主线程 [英] Visual Basic, Child Thread Blocking Main Thread

查看:230
本文介绍了Visual Basic,子线程阻塞主线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个小问题,一个简单的文件复制应用程序我写在Visual Basic 2005.我有一个主线程,照顾的GUI,并为文件扫描/复制我已经创建了一个单独的我创建的线程如下:

  trd_copy =新线程(AddressOf CopyTask)
trd_copy.IsBackground = True
trd_copy.Start()

这适用于操作的扫描阶段,使用GUI中的按钮就好了。问题是,当CopyTask进入文件复制阶段(使用File.Copy),主线程似乎锁定,并且GUI,它意味着我有用于中止复制操作的按钮是无用的。复制完成后,所有操作都返回正常状态,复制过程中子线程可以更新主窗体上的状态栏。





非常感谢!

p> Edit:添加CopyTask()的代码:

  Private Sub CopyTask()
Control.CheckForIllegalCrossThreadCalls = False
如果check_scanfirst.Checked then
status1.Text =Scanning ...
bytestocopy = 0
scandir(src)

filesscanned = True
MsgBox(扫描完成)
结束如果

如果check_delete.Checked然后
'清除目的地,删除任何不存在的文件源dir
结束如果

如果filesscanned那么
ProgressBar1.Visible = True
ProgressBar1.Minimum = 0
ProgressBar1.Maximum = 100
ProgressBar1.Refresh()
结束如果

checkdir(src)
MsgBox(复制完成)
如果filesfailed> 0 Then
MsgBox(警告:+ Str(filesfailed)+文件未成功复制。)
结束如果
guistop()
结束子


解决方案

从我可以告诉所有调用系统也是基于GUI线程无论你想要他们与否。和Control.CheckForIllegalCrossThreadCalls = False是非常糟糕,你总是想写你的线程和(如果初学者)运行代码,每次它突破代码写一个委托和调用函数的那部分你的线程(占据最多



这里是一个完整源代码的示例



http://www.codeproject.com / articles / 15104 /多线程与VB-NET-A-beginner-s选择


/ p>

Control.CheckForIllegalCrossThreadCalls = False - 这需要移除
如果check_scanfirst.Checked Then - 这需要一个委托和调用方法
status1.Text =Scanning ... - 这需要一个委托和调用方法
bytestocopy = 0
scandir(src) - 如果scandir(调用gui)一个委托和调用方法,但在Scandir()内部

  filesscanned = True 
MsgBox(Scanning completed - 这需要一个委托和调用方法(记住线程将继续运行即使mesgbox未点击)
结束如果

如果check_delete.Checked然后 - 这需要一个委托和调用方法
'清除目的地,删除源目录中不存在的任何文件
结束如果

如果filesscanned则
ProgressBar1.Visible = True - 这需要一个委托和调用方法
ProgressBar1.Minimum = 0 - 这需要一个委托和调用方法
ProgressBar1.Maximum = 100 - 这需要一个委托和调用方法
ProgressBar1 .Refresh() - 这需要一个委托和调用方法
End If

checkdir(src)
MsgBox(Copying completed) - 这需要一个委托和调用方法
如果filesfailed> 0)
MsgBox(Warning:+ Str(filesfailed)+文件未成功复制) - 这需要一个委托和调用方法
End If
guistop - 如果(guistop调用gui)需要一个委托和调用方法


我会如何写这篇文章?




  Private sub DoStuffBeforeCopy )
如果check_scanfirst.Checked那么
status1.Text =正在扫描...
bytestocopy = 0
trd_copy.ParameterizedStart(src)//开始线程
end sub

CopyTask(byval src as * string *?)
scandir(src) - 将代码放在这里或者做另一个线程(src更好)
filesscanned = True

invoke-MsgBox(扫描完成)

调用如果check_delete.Checked然后

如果filesscanned然后
Invoke-ProgressBar1.Visible = True
Invoke-ProgressBar1.Minimum = 0
Invoke-ProgressBar1.Maximum = 100
Invoke-ProgressBar1.Refresh()
结束如果

checkdir src) - 将代码放在这里或者做另一个线程(src更好)

invoke-MsgBox(Copying completed)

如果filesfailed> 0然后
Invoke-MsgBox(警告:+ Str(filesfailed)+文件未成功复制。)
结束如果

guistop这里或另一个线程(src更好)

结束子

对于任何代理/调用需要


b

trd_copy.ParameterizedStart(src)

 委托Sub nameofDelegate s As Integer)
Sub nameofDelegate + NameofSub(ByVal s As Integer)
如果Form1.ProgressBar1.InvokeRequired然后
Dim d As New nameofDelegate(AddressOf nameofDelegate + NameofSub)
NameOfYourForm。 Invoke(d,New Object(){s})
如果s = 1那么
NameOfYourForm.ProgressBar1.Refresh()**或其他Gui函数
Else

结束如果
结束如果
结束Sub




无参数的线程调用


trd_copy.Start()


$ b b

 委托Sub nameofDelegate()
Sub nameofDelegate + NameofSub()
如果Form1.ProgressBar1.InvokeRequired然后
Dim d As New nameofDelegate nameofDelegate + NameofSub)
NameOfYourForm.Invoke(d,New Object())
Else
NameOfYourForm.ProgressBar1.Refresh()**或其他Gui函数
End If
End Sub


I've run into a little issue with a simple file copying application I'm writing in Visual Basic 2005. I have a main thread which looks after the GUI, and for the file scanning/copying I've created a separate thread which I create like this:

    trd_copy = New Thread(AddressOf CopyTask)
    trd_copy.IsBackground = True
    trd_copy.Start()

This works fine for the scanning phase of the operation, and I can use the buttons in the GUI just fine. The problem is that when CopyTask gets to the file copying phase (using File.Copy), the main thread appears to lock up, and the GUI with it, meaning that the button I have there for aborting the copy operation is useless. When the copying is done, all returns to normal, and during copying the sub thread can update the status bar on the main form.

I'm sure I'm missing something simple, but I can't for the life of me see what it is.

Thanks very much!

Edit: Adding the code for CopyTask():

Private Sub CopyTask()
    Control.CheckForIllegalCrossThreadCalls = False
    If check_scanfirst.Checked Then
        status1.Text = "Scanning..."
        bytestocopy = 0
        scandir(src)

        filesscanned = True
        MsgBox("Scanning completed")
    End If

    If check_delete.Checked Then
        ' Do a clean of the destination, removing any files that don't exist in the source dir
    End If

    If filesscanned Then
        ProgressBar1.Visible = True
        ProgressBar1.Minimum = 0
        ProgressBar1.Maximum = 100
        ProgressBar1.Refresh()
    End If

    checkdir(src)
    MsgBox("Copying completed")
    If filesfailed > 0 Then
        MsgBox("Warning: " + Str(filesfailed) + " files were not copied successfully.")
    End If
    guistop()
End Sub

解决方案

From what i can tell all calls to the System are also GUI Thread based no matter if you want them or not. And Control.CheckForIllegalCrossThreadCalls = False is very bad, you always want to write your thread and ( if beginner ) run code and everytime it breaks out to code to write a delegate and an invoke function for that part of your thread ( taking up the most minimal time ) one can in the Gui(Main) thread.

Here is an example with full sourcecode

http://www.codeproject.com/Articles/15104/Multithreading-with-VB-NET-A-beginner-s-choice

in your thread

Control.CheckForIllegalCrossThreadCalls = False -- this needs removed If check_scanfirst.Checked Then -- this needs a delegate and invoke method status1.Text = "Scanning..." -- this needs a delegate and invoke method bytestocopy = 0 scandir(src) -- if scandir(has calls to gui )this needs a delegate and invoke method but inside of Scandir()

    filesscanned = True
    MsgBox("Scanning completed")              -- this needs a delegate and invoke method ( keep in mind thread will keep running even if mesgbox not clicked )
End If

If check_delete.Checked Then              -- this needs a delegate and invoke method
    ' Do a clean of the destination, removing any files that don't exist in the source dir
End If

If filesscanned Then
    ProgressBar1.Visible = True             -- this needs a delegate and invoke method
    ProgressBar1.Minimum = 0             -- this needs a delegate and invoke method
    ProgressBar1.Maximum = 100             -- this needs a delegate and invoke method
    ProgressBar1.Refresh()             -- this needs a delegate and invoke method
End If

checkdir(src)
MsgBox("Copying completed")             -- this needs a delegate and invoke method
If filesfailed > 0 Then
    MsgBox("Warning: " + Str(filesfailed) + " files were not copied successfully.")             -- this needs a delegate and invoke method
End If
guistop()             -- this needs a delegate and invoke method if (guistop makes calls to gui )

so if you can't tell your making lots of calls to the gui... heres how i would write it to make it really simple

how i would write your code ( wrote this in word some code may need a tweak )

Private sub DoStuffBeforeCopy()
If check_scanfirst.Checked Then
    status1.Text = "Scanning..."
    bytestocopy = 0
trd_copy.ParameterizedStart(src) //start thread
end sub

CopyTask(byval src as *string*?)
    scandir(src) – put the code here or make another thread ( src is better )
    filesscanned = True

    invoke-MsgBox("Scanning completed")

    invoke If check_delete.Checked Then

    If filesscanned Then
        Invoke-ProgressBar1.Visible = True
        Invoke-ProgressBar1.Minimum = 0
        Invoke-ProgressBar1.Maximum = 100
        Invoke-ProgressBar1.Refresh()
    End If

    checkdir(src) – put the code here or make another thread ( src is better )

    invoke-MsgBox("Copying completed")

    If filesfailed > 0 Then
        Invoke-MsgBox("Warning: " + Str(filesfailed) + " files were not copied successfully.")
    End If

    guistop()– put the code here or make another thread ( src is better )

End sub

** DO THIS FOR ANY Delegat / invoke needed

for threads calls with parameters

trd_copy.ParameterizedStart(src)

Delegate Sub nameofDelegate(s As Integer)
Sub nameofDelegate+NameofSub(ByVal s As Integer)
    If Form1.ProgressBar1.InvokeRequired Then
        Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
        NameOfYourForm.Invoke(d, New Object() {s})
    Else
        If s = 1 Then
            NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
        Else

        End If
    End If
End Sub

For Thread calls without parametrs

trd_copy.Start()

Delegate Sub nameofDelegate()
Sub nameofDelegate+NameofSub()
    If Form1.ProgressBar1.InvokeRequired Then
        Dim d As New nameofDelegate (AddressOf nameofDelegate+NameofSub)
        NameOfYourForm.Invoke(d, New Object())
    Else
       NameOfYourForm.ProgressBar1.Refresh() ** Or other Gui Functions
    End If
End Sub

这篇关于Visual Basic,子线程阻塞主线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆