1

我在 Visual Basic 2005 中编写的一个简单的文件复制应用程序遇到了一个小问题。我有一个负责 GUI 的主线程,对于文件扫描/复制,我创建了一个单独的线程,我像这样创建:

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

这适用于操作的扫描阶段,我可以很好地使用 GUI 中的按钮。问题是,当 CopyTask 进入文件复制阶段(使用 File.Copy)时,主线程似乎被锁定,并且 GUI 与它一起,这意味着我用于中止复制操作的按钮是无用的。复制完成后一切恢复正常,复制过程中子线程可以更新主窗体的状态栏。

我确定我错过了一些简单的东西,但我无法终生看到它是什么。

非常感谢!

编辑:添加 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
4

1 回答 1

1

据我所知,无论您是否想要它们,所有对系统的调用也是基于 GUI 线程的。并且 Control.CheckForIllegalCrossThreadCalls = False 非常糟糕,你总是想编写你的线程并(如果是初学者)运行代码并且每次它爆发为你的线程的那一部分编写委托和调用函数的代码(占用最多最短时间)可以在 Gui(Main) 线程中。

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

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

在你的线程中

Control.CheckForIllegalCrossThreadCalls = False -- 这需要删除 If check_scanfirst.Checked Then -- 这需要一个委托并调用方法 status1.Text = "Scanning..." -- 这需要一个委托并调用方法 bytestocopy = 0 scandir(src) -- 如果 scandir(调用了 gui)这需要一个委托和调用方法,但在 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 )

因此,如果您无法告诉您对 gui 进行了很多调用...这就是我将如何编写它以使其变得非常简单

我将如何编写您的代码(用文字写成,有些代码可能需要调整)

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

* *为任何需要的委托/调用执行此操作

对于带参数的线程调用

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

对于没有参数的线程调用

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
于 2013-06-24T17:58:59.367 回答