Прежде чем начать, я знаю, что уже есть куча ответов на этот вопрос, но позвольте мне объяснить, что происходит.Как установить текст в элемент, созданный в другом потоке
Я в основном хочу добавить некоторые тексты к элементу RichTextBox, он служит мне как регистратору для информирования пользователя о каждом действии от обработки файлов, но текст добавляется к RichTextBox через цикл for, и если я выполняю этот цикл в том же классе «Form1.vb» пользовательский интерфейс зависает до завершения цикла.
Я решил запустить цикл в отдельном потоке, чтобы избежать зависания пользовательского интерфейса, и вот здесь начинается моя проблема.
Form1.vb
Imports System.Threading
Public Class Form1
Dim myThread As Thread
Private Sub appendMyText()
' Cross-thread operation not valid: Control txtLogger accessed from a thread other than the thread it was created on.
txtLogger.AppendText("Hello World" & vbNewLine)
End Sub
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click
myThread = New Thread(New ThreadStart(AddressOf appendMyText))
myThread.Start()
End Sub
End Class
я не могу получить доступ к элементу txtLogger из другого потока, поэтому я попробовал пример MSDN https://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
Он показывает мне, как получить доступ к элементу делая потокобезопасные вызовы, используя делегат.
Так что мой отредактированный код
Form1.vb
Imports System.Threading
Public Class Form1
Dim myThread As Thread
Delegate Sub AppendMyText(ByVal text As String)
' Add the text to RichTextBox
Private Sub addText(ByVal txt As String)
If txtLogger.InvokeRequired Then
Dim myDelegate = New AppendMyText(AddressOf addText)
Me.Invoke(myDelegate, {txt})
Else
txtLogger.AppendText(txt)
End If
End Sub
' Call the method that add text to RichTextBox
Private Sub threadSafe()
Me.addText("Hello World" & vbNewLine)
End Sub
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click
myThread = New Thread(New ThreadStart(AddressOf threadSafe))
myThread.Start()
End Sub
End Class
код действительно работает таким образом, текст добавляется в RichTextBox, но весь код в одном классе Form1.vb
В моем исходном проекте цикл for выполняется в другом классе, я назову его «Class1.vb» здесь.
Вот пример кода
Class1.vb
Public Class Class1
Public Sub count()
Dim i As Integer
For i = 0 To 100
' this method will be executed by thread "myThread"
' how to append text to txtLogger from here?
Debug.WriteLine("Index: {0}", i)
Next
End Sub
End Class
Вы можете передать форму в качестве параметра методу 'count'. –
Я уже пробовал этот путь. Но доступ к элементам из другого потока напрямую не рекомендуется, и я знаю, почему! Мой проект должен добавить текст более 200 раз, и приложение перестает отвечать и разбивается, когда я передаю форму как параметр, потому что форма запускается на нем собственной нитью. –
Доступ к настраиваемому методу через форму должен быть настолько длинным, чтобы этот метод вызывал доступ к элементам пользовательского интерфейса. –