Update Text Box Properly when Cross-threading in Visual Basic (VS 2012 V11)

后端 未结 2 1785
别跟我提以往
别跟我提以往 2021-01-22 15:58
  • 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?

    <
相关标签:
2条回答
  • 2021-01-22 16:28

    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
    
    0 讨论(0)
  • 2021-01-22 16:43

    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
    
    0 讨论(0)
提交回复
热议问题