DOBON.NET DOBON.NETプログラミング掲示板過去ログ

別のスレッド、別のクラスからコントロールを操作するには?

環境/言語:[WinXP、VB.NET、.NET Framework3.5]
分類:[.NET]

こんにちは。質問させて頂きます。
ずばり、タイトルの通り、別のスレッド、別のクラスからコントロールを
操作するにはどうすれば良いかで悩んでいます。
色々とサイトを眺めてみて、フォームを作成したスレッドと別のスレッドから
コントロールを操作するにはデリゲートの作成が必要らしいということで
下記のようなコードを試してみたのですが、どうも上手くいきません。
意図としてはButton1を押すとBackgroundworker1が走り、その中から
TextBox1のTextを"test1"と書き換えてくれることを期待しているのですが、
実際にはButton1を押してもTextBox1に何の変化も見られません。
どうすれば書き換わるようになるのでしょうか?
以上、よろしくご回答御願い致します。

Public Class Form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
BackgroundWorker1.RunWorkerAsync()
End Sub

Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim _testClass1 As testClass1 = New testClass1
_testClass1.testsub()
End Sub

Delegate Sub Set_Control_textCallback _
(ByVal Target_Control As Control, ByVal _text As String)

Public Sub Set_Control_text(ByVal Target_Control As Control, ByVal _text As String)

If Target_Control.InvokeRequired Then
Dim d As New Set_Control_textCallback(AddressOf Set_Control_text)
Me.Invoke(d, Target_Control, _text)
Else
Target_Control.Text = _text
End If
End Sub

End Class

Public Class testClass1

Public Sub testsub()
Form1.Set_Control_text(Form1.TextBox1, "test1")
End Sub
End Class
■No30863に返信(あかつきさんの記事)

BackgroundWorkerを使っているならReportProgressすればUIスレッドに制御を戻すことが出来るのでInvokeしなくてもFormのコントロールにアクセス出来ます。


提示コードを直すなら
> _testClass1.testsub()
_testClass1.testsub(Me)


> Public Sub testsub()
> Form1.Set_Control_text(Form1.TextBox1, "test1")
> End Sub
Public Sub testsub(fm1 As Form1)
fm1.Set_Control_text(fm1.TextBox1, "test1")
End Sub

実行スレッド中にForm1のインスタンスがないためForm1の記述にすると
新しいインスタンスが作成されてしまう。
shuさん有難う御座います。
参考にさせて頂きます。

■No30864に返信(shuさんの記事)
> ■No30863に返信(あかつきさんの記事)
>
> BackgroundWorkerを使っているならReportProgressすればUIスレッドに制御を戻すことが出来るのでInvokeしなくてもFormのコントロールにアクセス出来ます。
>
>
> 提示コードを直すなら
>>_testClass1.testsub()
> _testClass1.testsub(Me)
>
>
>> Public Sub testsub()
>> Form1.Set_Control_text(Form1.TextBox1, "test1")
>> End Sub
> Public Sub testsub(fm1 As Form1)
> fm1.Set_Control_text(fm1.TextBox1, "test1")
> End Sub
>
> 実行スレッド中にForm1のインスタンスがないためForm1の記述にすると
> 新しいインスタンスが作成されてしまう。
>
>
すいません、もう一度質問させて下さい。
shuさんのレスを読んで、呼び出し元のインスタンスを渡してやらないと
新しいインスタンスが生成されてしまうということは理解しました。
そこで、試しに次のような簡単なコードを組んでみたのですが・・・

Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim _testClass1 As testClass1 = New testClass1
_testClass1.readtext()
End Sub
End Class

Public Class testClass1
Public Sub readtext()
Dim _readtext As String = Form1.TextBox1.Text
Debug.Print("TextBox1:" & _readtext)
End Sub
End Class

Button1を押すとTextBox1のテキストをイミディエイトウィンドウに
表示するというだけのものですが、ここでtest1Class1.readtextメソッドを
呼び出す際に、呼び出し元のインスタンスを与えていないのに
ちゃんと処理をしてくれるのはなぜなのでしょうか?
30863と比べた際の動き方の違いの理由が分かりません。
以上、ご回答頂けると有り難いです。
宜しく御願い致します。
■No30866に返信(あかつきさんの記事)

スレッドが同じか違うかです。

>> 実行スレッド中にForm1のインスタンスがないためForm1の記述にすると
これ。


サンプル:
Public Class Form1

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        BackgroundWorker1.RunWorkerAsync()
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim newa As New a()
        newa.test()
    End Sub
End Class

Public Class a
    Public Sub test()
        Form1.Text = Form1.Handle.ToString
        Form1.ShowDialog()
    End Sub
End Class
理解できました。
shuさん、有難うございました。

■No30867に返信(shuさんの記事)
> ■No30866に返信(あかつきさんの記事)
>
> スレッドが同じか違うかです。
>
> >> 実行スレッド中にForm1のインスタンスがないためForm1の記述にすると
> これ。
>
>
> サンプル:
> Public Class Form1
>
> Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
> BackgroundWorker1.RunWorkerAsync()
> End Sub
>
> Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
> Dim newa As New a()
> newa.test()
> End Sub
> End Class
>
> Public Class a
> Public Sub test()
> Form1.Text = Form1.Handle.ToString
> Form1.ShowDialog()
> End Sub
> End Class
■No30871に返信(あかつきさんの記事)
> 理解できました。
> shuさん、有難うございました。
>
> ■No30867に返信(shuさんの記事)
>>■No30866に返信(あかつきさんの記事)
>>
>>スレッドが同じか違うかです。
>>
>>>> 実行スレッド中にForm1のインスタンスがないためForm1の記述にすると
>>これ。
>>
>>
>>サンプル:
>>Public Class Form1
>>
>> Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
>> BackgroundWorker1.RunWorkerAsync()
>> End Sub
>>
>> Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
>> Dim newa As New a()
>> newa.test()
>> End Sub
>>End Class
>>
>>Public Class a
>> Public Sub test()
>> Form1.Text = Form1.Handle.ToString
>> Form1.ShowDialog()
>> End Sub
>>End Class
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板