質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.33%

  • VB.NET

    967questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

  • VB

    312questions

    VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

  • スレッドセーフ

    15questions

    マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。

別スレッドからフォームへのコントロールアクセス

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 897

abanda

score 4

.NET Framework4.5 
言語:Visual Basic 
Windowsフォームアプリケーション

いつもお世話になっております。
また皆様のお力を借りたく、質問させて頂きます。

色々なことの勉強の為にTCP通信を用いてクライアント側から文字が送信されたらサーバー側が返事をするようなアプリを作ろうとしています。

TCP通信をサブスレッドで行っており、サブスレッドからフォームのコントロールを操作して、テキストボックスに送受信文字を書き込みたいです。

メインスレッド、サブスレッドをあまり意識せずにテキストボックスに送受信文字を書き込めるようにしたい為、ネットのサンプルを流用し、モジュールにSetAppendTextというメソッドを作りました。

Public Sub SetAppendText(ByVal target As TextBox, ByVal value As String)

        Try
            'Dim ac As New Action(Of String)(Sub(v) target.Text = v)
            Dim ac As New Action(Of String)(Sub(v) target.AppendText(v + vbCrLf))

            If target.InvokeRequired Then
                target.Invoke(ac, New Object() {value})
            Else
                ac(value)
            End If
        Catch ex As ObjectDisposedException
            Return
        End Try

    End Sub

↑のメソッドを使って、サブスレッド側でフォームと書き込みたい文字を引数に渡しているのですが、テキストボックスに表示されません。(Formクラスと別スレッドを開始しているクラスは別です。これを同じクラスにすると文字の書き込みは行われます。)

おそらく、渡している引数が悪いと思うのですが、いまひとつ原因がわかりません。

この質問内容だけではプログラム全体が把握できないと思うので、該当のプログラムをこちらからDLしてもらい見てもらえれば幸いです。↓
リンク内容(PASSWORD:今年の西暦4桁を数字で)

プロジェクトが二つ(クライアント側とサーバー側)入っています。
スタートボタンで接続を開始してもらい、クライアント側で何か文字を送っていただければ、クライアント側には送信文字と受信文字がテキストボックスに書き込まれると思います。

質問該当箇所(例)

'//ログの書き込み
CommonMethod.SetAppendText(ServerForm.LogTextArea, "クライアントが接続しました。")

CommonMethod.SetAppendText(ServerForm.LogTextArea, "接続停止  " + ex.ToString())

'ログへの書き込み
CommonMethod.SetAppendText(ServerForm.LogTextArea, "クライアントが切断されました。")
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

さっと見た感じServerListen内で使用しているServerFormが別物として新たに作成されています。
このため、ServerStart内で使用されるServerFormは表示されているもの
ServerListen内で使用されるのは新たに作成された表示されていないServerFormとなっています。

別スレッドからはMy.MyProject.MyFormsを使うのではなく

Private MainForm As ServerForm

Public Sub New(UI As ServerForm)
    MainForm = UI
End Sub


と変数宣言、コンストラクタを作成し

CommonMethod.SetAppendText(MainForm.LogTextArea, "クライアントが接続しました。")


と呼べばよいかと

また、今回の件とは直接関係がありませんが、TCPクラス内でフォーム側のデザインに左右されるような作りをしないほうが良いと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/24 20:29

    前回質問に引き続き回答ありがとうございます!
    おかげさまでテキストボックスに書き込みができるようになりました。

    だけど、”TCPクラス内でフォーム側のデザインに左右されるような作りをしないほうが良い”とはどういうことでしょうか?(フォーム側のデザインに左右されるとはいったい・・・)
    また、この場合はどういった作りにするのが良い作りといわれるのでしょうか?

    重ねて質問になってしまい、申し訳ありませんが、よろしければ返答をお願いいたします。

    キャンセル

  • 2017/02/24 21:50

    今回の場合ですが、TCPクラスはServerFormというフォームやLogTextAreaというTextboxコントロール等がある前提で作成されています。

    機能的にTCPクラスは通信を行うクラスですので、画面の更新は機能外となるわけです。
    機能をしっかり分離しておけば、使いまわしの制限もなくなっていきます。
    (現状ですとServerFormという型のフォームがあり、それにLogTextAreaというTextboxコントロールがないと使用できないクラスということになります)

    例えば、TCPクラスで通信の待ち受けポートを設定しようとします。
    フォーム上にポート番号を入力するテキストボックス(PortInputTextBox)があるとします。

    TCPクラス内から
    port = From.PortInputTextBox.text
    と参照するのではなくて

    TCPクラスに
    Public Property Port() As Integer
    とプロパティを作り、フォームから
    TCP.Port = Integer.Parse(PortInputTextBox.Text)
    とすれば、TCPクラス側はコントロールの有無に左右されなくなります。

    TCPクラスで受信したデータを画面に表示する場合は
    TCPクラスに
    Public Event DataRecived(data As String)
    と定義して、データ受信時に
    RaiseEvent DataRecived(recvData)
    とイベントを発生させます。

    フォーム側で(Private WithEvents TCP As TCPClassと定義してあると仮定)
    Private Sub TCP_DataRecived(data As String) Handles TCP.DataRecived
      LogTextbox.Text = data
    End Sub
    とすれば、TCPクラスはテキストボックスがあることを知らなくても良くなります。
    (あくまで例なので、スレッド等は考慮してありません)

    こういった設計思想はいろいろなところで書かれていますから、調べてみるといいですよ。

    キャンセル

  • 2017/02/25 22:09

    なるほど~
    機能分離をしっかりさせることが大事なのですす、勉強になります
    ありがとうございました
    また何かあればよろしくお願いします

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • VB.NET

    967questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

  • VB

    312questions

    VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

  • スレッドセーフ

    15questions

    マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。