简而言之,这是我的问题:如何使用 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
除了更新 textbox3 中的文本外,该代码工作正常。当指定的文件被修改时,我需要更新文本框。这很重要,以便用户可以知道程序正在运行并获得程序操作的完整日志。
导致的错误是:
跨线程操作无效:控件“TextBox3”从创建它的线程以外的线程访问。
我假设“AddHandler varFileSystemWatcher.Changed,AddressOf OnChanged”创建了一个新线程。此外,在“OnChange Sub”中更新“textbox3”(以我的方式)不是线程安全的方式。所以我做了一些研究,发现了这篇文章:
该文章解释说,可以使用 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
上面代码的许多部分让我感到困惑。它有什么作用?我需要这段代码的哪些部分来使用 BackgroundWorker?InvokeRequired 方法的哪些部分?同样,如何使用 BackGroundWorker(或 InvokeRequired 方法)进行线程安全调用以将文本附加到文本框?(解释上面的代码会很棒,但我真正需要的只是一个如何以线程安全的方式更新文本框文本的示例。)