シリアル通信での計測プログラムの作り方について

解決


中家  2023-09-18 08:29:33  No: 151104  IP: [192.*.*.*]

リレーを切り替えて数十点の電圧を監視する装置を作っています。
シリアル通信は金澤ソフト設計さん
https://kana-soft.com/tech/sample_0008_4.htm
のサンプルソフトを拝借しました。
測定開始ボタンでのイベント処理関数内にループを作ってリレースキャンさせると
データ受信してくれないことが分かりました。
(サンプルソフトの
'*  @brief  受信データをテキストボックスに書き込む.
    Private Sub RcvDataToTextBox( data As String )
へ処理が来ない

試行錯誤の末、測定開始ボタンでDoCommandにフラグを立てて関数を完了させ、
サンプルソフトの
    Private Sub RcvDataToTextBox( data As String )
        If IsNothing(data) = False Then
            writer.Write(data)
            If DoCommand = 1 Then

のようにデータ受信が発生するたびにDoCommandを監視して
次の処理を行い、かろうじてデータ読み取りできるようになったのですが、
もっとスマートな方法を教えてください。
Invoke()がキーがなと思って調べましたが理解できませんでした。
よろしくお願いいたします。
 

編集    削除
KOZ  2023-09-18 16:32:43  No: 151105  IP: [192.*.*.*]

Windows プログラムは、メッセージキューより Windows メッセージを取り出して処理するループ(メッセージループ)が走っています。
このループ処理を行うスレッドのことを UI スレッドと呼びます。

Invoke メソッドは、UI スレッドに処理を依頼します。
具体的には、メッセージキューに、処理してくれというメッセージを登録し、処理されるのを待ちます。

測定開始ボタンのイベント処理は UI スレッドです。
イベント処理関数を抜ければメッセージループの処理に戻れますが、関数内にループを作ると戻れません。

なので、RcvDataToTextBox が動かないのです。

回避するには、リレースキャンの処理を UI スレッドとは別のスレッドで行えば良いことになります。

Task とか、Await などのキーワードを調べると幸せになれるかも。

編集    削除
中家  2023-09-20 16:13:26  No: 151108  IP: [192.*.*.*]

KOZさん、アドバイスありがとうございます。
取り組んでいますが、Taskに付いた下波エラーがどうしても消えません。
https://webbibouroku.com/Blog/Article/async-await-taskのサンプルを拝借して、
Private Async Function Sample3Async() As Task
        Dim result As Integer = Await Task.Run(
        Function() As Integer
            For Index = 0 To Integer.MaxValue - 1
            Next
            Return 1
        End Function
    )
        Console.WriteLine("タスク完了:{0}", result)
    End Function
を入れてみましたが、同じです。
”T”を入力すると候補が”Tab”,”TabAlignment”など出てきますが、”Task”はありません。
これは問題ないですか。

編集    削除
KOZ  2023-09-21 09:45:47  No: 151112  IP: [192.*.*.*]

こんな感じです。

Private Async Function Sample3Async() As Task(Of Integer)
    Dim result As Integer = Await Task.Run(
    Function() As Integer
        For Index = 0 To Integer.MaxValue - 1
        Next
        Return 1
    End Function
)
    Console.WriteLine("タスク完了:{0}", result)
    Return result
End Function

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim result = Await Sample3Async()
    Console.WriteLine($"戻り値:{result}")
End Sub

編集    削除
KOZ  2023-09-21 10:26:41  No: 151113  IP: [192.*.*.*]

普通に書くと

Private Function Sample3Async() As Integer
    For index = 0 To Integer.MaxValue - 1
    Next
    Dim result = 1
    Console.WriteLine("タスク完了:{0}", result)
    Return result
End Function

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim result = Await Task.Run(Function() Sample3Async())
    Console.WriteLine($"戻り値:{result}")
End Sub

編集    削除
中家  2023-09-21 13:58:06  No: 151115  IP: [192.*.*.*]

KOZさん、ありがとうございます。
このまま使えそうで、すぐに試したいのですが、
Taskが使えないようです。
Taskは、新しいプロジェクトを作ってやると問題なく使えるので、
ネットから拝借したサンプルを切り貼りしたのが原因と思います。
新しいプロジェクトで作り直して使わせていただきます。

編集    削除
KOZ  2023-09-21 14:12:59  No: 151116  IP: [192.*.*.*]

> Taskが使えないようです。
Task が使えるのは .NET Framework 4.5 からです。
もしくは Imports System.Threading.Tasks を削除しちゃったのでは?

編集    削除
中家  2023-09-21 17:18:03  No: 151118  IP: [192.*.*.*]

新しいプロジェクトへ作業中の情報を入れようとして苦労しているところです。
Form1.vb、Form1.Designer.vbをそのままコピーしてもダメで、
テキストを編集してもエラーが消えずに困っています。
VBのバージョンは2016で、ターゲットフレームワークは.NET Framework 4.7.2にしています。
Imports System.Threading.Tasks をTaskが使えるプロジェクトのファイルで探してみましたが、
見つけることができません。どこにあればいいのでしょうか。
教えてください。

編集    削除
KOZ  2023-09-21 18:13:13  No: 151120  IP: [192.*.*.*]

VB2016って何でしょうか?
2015 とか 2017 ならわかるんですが。
.NET Framework 4.7.2 なら、使えるはずなのですけども。
https://learn.microsoft.com/ja-jp/dotnet/api/system.threading.tasks.task?view=netframework-4.7.2

編集    削除
KOZ  2023-09-21 22:03:04  No: 151122  IP: [192.*.*.*]

Task クラスのリファレンスに「定義」ってありますよね?
そこを見ると
名前空間:
System.Threading.Tasks
アセンブリ:
mscorlib.dll
となっています。
mscorelib.dll というのは、必ず参照されるアセンブリなので、無いはずがないのです。
エラーメッセージにはなんて書いてあるんでしょうか?

編集    削除
中家  2023-09-21 23:03:57  No: 151123  IP: [192.*.*.*]

たくさん、ありがとうございます。
VB2019です、間違えました。
エラーというか、良いプロジェクトはTaskの色が変わりますが、
使えないほうは色が変わらず、Taskの下に赤い小波アンダーラインが出ます。
デバッグ開始すると、
: error BC30451: 'Task' は宣言されていません。アクセスできない保護レベルになっています。
が出ます。
試行錯誤の末にname.vbprojを替えるとTaskがサポートされることが分かり、
中を見ると <ItemGroup>に
    <Import Include="System.Threading.Tasks" />
 が無いことが分かりました。
ご指摘の通りだったと思います。
外したわけではないのですが、古いバージョンで作ったのを新しいバージョンで、
dataacqのアプリケーションの
ターゲットフレームワークを変更するだけではだめなんでしょうか。
これから教えていただいたように作り変えます。

編集    削除
中家  2023-09-22 00:23:15  No: 151124  IP: [192.*.*.*]

「普通に書くと」
の方でうまく動いてくれました。(もう一つはまだ試していません)
何回か試しましたが誤動作は無かったです。
助かりました、本当にありがとうございます。

編集    削除