在Visual Basic中交叉线程时正确更新文本框(V​​S 2012 V11)

use*_*797 2 vb.net multithreading textbox backgroundworker

  • 以下是我的问题:如何使用BackGroundWorker(或InvokeRequired方法)进行线程安全调用以将文本追加到文本框中?

  • 这是我的问题,有很多细节和背景:我一直致力于将文件从一个位置复制到另一个位置以进行备份的程序.我设置了一个选项,当使用FileSysteWatcher修改文件时将保存文件.这是代码:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
    
        Dim directoryPath As String = Path.GetDirectoryName(TextBox1.Text)
        Dim varFileSystemWatcher As New FileSystemWatcher()
        varFileSystemWatcher.Path = directoryPath
    
        varFileSystemWatcher.NotifyFilter = (NotifyFilters.LastWrite)
        varFileSystemWatcher.Filter = Path.GetFileName(TextBox1.Text)
        AddHandler varFileSystemWatcher.Changed, AddressOf OnChanged
        varFileSystemWatcher.EnableRaisingEvents = True
    
    End Sub
    
    Private Sub OnChanged(source As Object, ByVal e As FileSystemEventArgs)
    
        My.Computer.FileSystem.CopyFile(e.FullPath, TextBox2.Text & "\" & e.Name, True)
        TextBox3.ApendText("[New Text]") ' This line causes an error
    End Sub
    
    Run Code Online (Sandbox Code Playgroud)

除了更新textbox3中的文本外,代码工作正常.我需要在修改指定文件时更新文本框.这很重要,以便用户可以知道程序正在运行并拥有程序操作的完整日志.

导致的错误是:

跨线程操作无效:控制从其创建的线程以外的线程访问的"TextBox3".

我假设"AddHandler varFileSystemWatcher.Changed,AddressOf OnChanged"创建一个新线程.此外,更新"OnChange Sub"中的"textbox3"(以我的方式)不是一种线程安全的方式.所以我做了一些研究,发现这篇文章:

如何:对Windows窗体控件进行线程安全调用

本文解释了可以使用InvokeRequired或BackgroundWorker进行线程安全调用.我想使用BackgroundWorker进行一个线程安全的调用(如果InvokeRequired效率更高,那么我将使用它),但是这个例子中提供的部分让我感到困惑:

' Do I need these imports to use the BackgroundWorker or InvokeRequired?
Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.Windows.Forms

Public Class Form1
   Inherits Form ' Do I need this for what I am trying to do?

   ' This delegate enables asynchronous calls for setting
   ' the text property on a TextBox control.
   Delegate Sub SetTextCallback([text] As String)

   ' This thread is used to demonstrate both thread-safe and
   ' unsafe ways to call a Windows Forms control.
   Private demoThread As Thread = Nothing

   ' This BackgroundWorker is used to demonstrate the 
   ' preferred way of performing asynchronous operations.
   Private WithEvents backgroundWorker1 As BackgroundWorker

   Private textBox1 As TextBox
   Private WithEvents setTextUnsafeBtn As Button
   Private WithEvents setTextSafeBtn As Button
   Private WithEvents setTextBackgroundWorkerBtn As Button

   ' What is this part of the code for and do I need it?
   Private components As System.ComponentModel.IContainer = Nothing

   ' Again, What is this part of the code for and do I need it?
   Public Sub New()
      InitializeComponent()
    End Sub

   ' And again, What is this part of the code for and do I need it?
   Protected Overrides Sub Dispose(disposing As Boolean)
      If disposing AndAlso (components IsNot Nothing) Then
         components.Dispose()
      End If
      MyBase.Dispose(disposing)
    End Sub
Run Code Online (Sandbox Code Playgroud)

上面代码的许多部分让我感到困惑.它有什么作用?使用BackgroundWorker需要使用此代码的哪些部分?InvokeRequired方法的哪些部分?同样,如何使用BackGroundWorker(或InvokeRequired方法)进行线程安全调用以将文本附加到文本框?(上面的代码解释得很好,但我真正需要的只是一个如何以线程安全的方式更新文本框文本的例子.)

Idl*_*ind 15

更改:

Private Sub OnChanged(source As Object, ByVal e As FileSystemEventArgs)
    My.Computer.FileSystem.CopyFile(e.FullPath, TextBox2.Text & "\" & e.Name, True)
    TextBox3.ApendText("[New Text]") ' This line causes an error
End Sub
Run Code Online (Sandbox Code Playgroud)

至:

Private Sub OnChanged(source As Object, ByVal e As FileSystemEventArgs)
    My.Computer.FileSystem.CopyFile(e.FullPath, TextBox2.Text & "\" & e.Name, True)
    AppendTextBox(TextBox3, "[New Text]")
End Sub

Private Delegate Sub AppendTextBoxDelegate(ByVal TB As TextBox, ByVal txt As String)

Private Sub AppendTextBox(ByVal TB As TextBox, ByVal txt As String)
    If TB.InvokeRequired Then
        TB.Invoke(New AppendTextBoxDelegate(AddressOf AppendTextBox), New Object() {TB, txt})
    Else
        TB.AppendText(txt)
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)