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(メイン)スレッドで実行できます。

これは完全なソースコードの例です

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 に答える