Here is my question in short: How do I use the BackGroundWorker (or InvokeRequired method) to make thread-safe calls to append text to a text box?
<Change:
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
To:
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
Here's an updated, simplified version that uses an anonymous delegate:
Private Sub OnChanged(source As Object, ByVal e As FileSystemEventArgs)
Dim filename As String = System.IO.Path.Combine(TextBox2.Text, e.Name)
Try
My.Computer.FileSystem.CopyFile(e.FullPath, filename, True)
TextBox3.Invoke(Sub()
TextBox3.AppendText("[New Text]")
End Sub)
Catch ex As Exception
Dim msg As String = "Source: " & e.FullPath & Environment.NewLine &
"Destination: " & filename & Environment.NewLine & Environment.NewLine &
"Exception: " & ex.ToString()
MessageBox.Show(msg, "Error Copying File")
End Try
End Sub
You can also use SynchronizationContext. Be careful to get a reference to it from the constructor. There's a great article on this at CodeProject.com: http://www.codeproject.com/Articles/14265/The-NET-Framework-s-New-SynchronizationContext-Cla
Imports System.IO
Imports System.Threading
Public Class Form1
Private m_SyncContext As System.Threading.SynchronizationContext
Private m_DestinationPath As String
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.m_SyncContext = System.Threading.SynchronizationContext.Current
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.m_DestinationPath = Me.TextBox2.Text
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, Me.m_DestinationPath & "\" & e.Name, True)
Me.m_SyncContext.Post(AddressOf UpdateTextBox, "[New Text]")
End Sub
Private Sub UpdateTextBox(param As Object)
If (TypeOf (param) Is String) Then
Me.TextBox3.AppendText(CStr(param))
End If
End Sub
End Class