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

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

新規登録して質問してみよう
ただいま回答率
85.35%
VB

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

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

VB.NET

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

Q&A

解決済

2回答

3168閲覧

VB.NET メッセージ出力

TEC_S

総合スコア79

VB

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

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

VB.NET

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

0グッド

1クリップ

投稿2020/02/06 07:10

前提・実現したいこと

Windows Formアプリケーションを作成しています。
VB6からVB.NETへの変換を行っています。VB6の時に動かしていた状態の機能をそのままでは再現できない為、マルチスレッド化を進めています。

処理をマルチスレッドにて動かす場合の、同一フォームへのメッセージ出力について、出力できずに困っています。

また、VBのマルチスレッドの扱い方についての理解がイマイチ進まない為、ご教授頂きたいと思います。よろしくお願いいたします。

発生している問題・エラーメッセージ

ThreadStateException: 現在のスレッドはシングル スレッド アパートメントでないため、ActiveX コントロール xxxx をインスタンス化できません。

該当のソースコード

MainFrom:メインフォーム

VBNET

1 2Private MyThred As Thread 3 4Private Sub MainFrom_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load 5 6 'スレッドスタート. 7 MyThred = New Thread(AddressOf Thread1) 8 MyThred .IsBackground = True 9 MyThred .Start() 10 11End Sub 1213141516 17'メインスレッド 18Sub Thread1() 19 Do 20 'ErrModOut("xxxx") '<- 元の処理(Moduleへ) 21 ErrMesOut("xxxxx") 22 Loop 23End Sub 24 25'エラー出力用 26Private Sub ErrMesOut(ByRef s As String) 27 ErrDispText.Text = "エラー:" & s 28End Sub

 
下記がModuleの処理

VBNET

1Module SubMod 234 Sub ErrModOut(ByRef s As String) 5 MainFrom.ErrDispText.Text = "エラー:" & s 6 End Sub 789End Module

試したこと

1)別Moduleからは、Fromにアクセスしない方が良いと考え、Form内にメッセージ出力用のメソッドを用意(現在の状態)※実際にはModuleでは別の処理もある

下記を参考に、自分のフォームに処理を追加
https://www.atmarkit.co.jp/ait/articles/0504/20/news111_2.html

2)エラーメッセージを検索したら、下記MSフォーラムが出てきた。
回避策として、<MTAThread()>を追加すると記載があった。
https://support.microsoft.com/ja-jp/help/841295/you-receive-a-system-threading-threadstateexception-exception-when-you

補足情報(FW/ツールのバージョンなど)

OS:Windows10
開発環境:Visual Studio2017 / .NetFramwerk4.6.1

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

提示されたコードのみでは、細部がはっきりしないのでアドバイスしづらいですが、一つだけ確実なのは別スレッドからフォームのコントロールに対してアクセスする(関数経由でも同じ)ことはできません。

今アクセス関数を作っているのであれば、その関数に対してデリゲート宣言をして、スレッド内の処理からInvoke関数を使って、デリゲートオブジェクトを呼び出してやる、ということをする必要があります。

Invoke,Delegate,スレッドなどのキーワードで検索すれば、非同期処理について詳しく解説しているサイトが見つかると思います。そちらを参考にされると良いと思います。

投稿2020/02/06 07:31

KoichiSugiyama

総合スコア3041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TEC_S

2020/02/06 13:04

情報が少ない中(申し訳ありません)ありがとうございます。 フォームのコントロールに対しては、スレッド内の処理からInvoke関数を使って、デリゲートオブジェクトを呼び出す。というのが、処理の方法なのですね。 >別スレッドからフォームのコントロールに対してアクセスする(関数経由でも同じ)ことはできません。  → 勘違いしていました。ありがとうございます。 Moduleからでも、Invoke関数を呼び出せば、可能という事でしょうか。。 例えば、下記のようなコード。 ```VBNET Module SubMod ・ ・ Private Delegate Function Del Sub ErrModOut(ByRef s As String)  If MainFrom.InvokeRequired Then Return MainFrom.Invoke(New Del(Function() ErrModOut(s)))  End If MainFrom.ErrDispText.Text = "エラー:" & s End Sub ・ ・ End Module ``` 参考:https://codezine.jp/article/detail/139 このコードだと、MainFromがNothingだと言われます。 MainFormのコントロールプロパティにInvokeRequired があると思っていますが、Nothingという事は、初期化するべきでしょうか。 根本的に何か・・・勘違いをしていますでしょうか。。 申し訳ありません。ご教授頂けますと幸いです。
KoichiSugiyama

2020/02/06 14:05

VBそれほど詳しくないのですが、VB6でよくあったフォーム名を直接指定して操作する、というやり方はVB.netでも一応使える場面もあるそうですが、通常はあまり推奨されていません。アプリケーションのメインフォームにアクセスしたいのであれば、WindowsFormsApplicationBase.MainForm プロパティを使ってメインフォームを取得すればよいと思います。
TEC_S

2020/02/06 16:47

ありがとうございます。 頂いたご意見(MainFormプロパティを取得させれば)が参考になり、解決となりました。
guest

0

自己解決

メインフォームから、ModuleへMainFromのインスタンスを渡した

VBNET

1Private Sub MainFrom_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load 2 3 'スレッドスタート. 4 SubMod.MainFrom = Me '<- 追加:Fromのインスタンスを渡す 5 MyThred = New Thread(AddressOf Thread1) 6 MyThred .IsBackground = True 7 MyThred .Start() 8 9End Sub

 
Module

VBNET

1Module SubMod 2 Property MainFrom 345Private Delegate Function Del 6Sub ErrModOut(ByRef s As String) 7 If MainFrom.InvokeRequired Then 8 Return MainFrom.Invoke(New Del(Function() ErrModOut(s))) 9 End If 10 MainFrom.ErrDispText.Text = "エラー:" & s 11 End Sub 121314End Module

投稿2020/02/06 16:52

TEC_S

総合スコア79

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問