2017-02-21 7 views
-1

開始する前に、すでにその質問に対する回答がたくさんありますが、何が起こっているのか説明してください。別のスレッドで作成された要素にテキストを設定する方法

基本的にRichTextBox要素にいくつかのテキストを追加したいのですが、ファイル処理からユーザーに各アクションを通知するように私に役立ちますが、テキストはforループを通してRichTextBoxに追加されます。このループは同じクラス "Form1.vb"でループが終了するまでUIがフリーズします。

私はUIのフリーズを避けるためにループを別のスレッドで実行することに決めました。ここで私の問題が始まります。

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 

で、テキストはリッチテキストボックスに追加されますが、それはすべてのコードが同じクラスになっています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 
+0

フォームをパラメータとして 'count'メソッドに渡すことができます。 –

+0

私はすでにこの方法を試みました。しかし、別のスレッドから要素に直接アクセスすることはお勧めできません。なぜか分かります!私のプロジェクトは200回以上テキストを追加する必要があり、フォームはそれ自身のスレッドで実行されるため、フォームをパラメータとして渡すと、アプリケーションは応答を停止し、クラッシュします。 –

+0

フォームを使用してカスタムメソッドにアクセスするには、そのメソッドがUI要素へのアクセスを呼び出す限り、依然として可能である必要があります。 –

答えて

2

はクラスにあなたの中に

フォームで

Dim MyClass as Class1 
MyClass = New Class1(Me) 

をフォームの参照を渡しますrクラス

Public Class Class1 

    Private Parent_From as Form1 
    Public Sub New(Parent as Form1) 
      Parent_From = Form 
    End sub 
    Public Sub count() 
     Dim i As Integer 
     For i = 0 To 100 
      ' this method will be executed by thread "myThread" 
      Parent_Form.addTExt("Whatever") 
      Debug.WriteLine("Index: {0}", i) 
     Next 
    End Sub 
End CLass 
+1

素晴らしい!出来た!私はすでにフォームとしてパラメータを渡そうとしましたが、代わりにParent_From.txtLogger.AppendText( "something")を使って要素にアクセスしていたのと同じメソッドを呼び出してテキストを追加するのを忘れていました。 –

関連する問題