リレーを切り替えて数十点の電圧を監視する装置を作っています。
シリアル通信は金澤ソフト設計さん
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()がキーがなと思って調べましたが理解できませんでした。
よろしくお願いいたします。
Windows プログラムは、メッセージキューより Windows メッセージを取り出して処理するループ(メッセージループ)が走っています。
このループ処理を行うスレッドのことを UI スレッドと呼びます。
Invoke メソッドは、UI スレッドに処理を依頼します。
具体的には、メッセージキューに、処理してくれというメッセージを登録し、処理されるのを待ちます。
測定開始ボタンのイベント処理は UI スレッドです。
イベント処理関数を抜ければメッセージループの処理に戻れますが、関数内にループを作ると戻れません。
なので、RcvDataToTextBox が動かないのです。
回避するには、リレースキャンの処理を UI スレッドとは別のスレッドで行えば良いことになります。
Task とか、Await などのキーワードを調べると幸せになれるかも。
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”はありません。
これは問題ないですか。
こんな感じです。
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
普通に書くと
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
KOZさん、ありがとうございます。
このまま使えそうで、すぐに試したいのですが、
Taskが使えないようです。
Taskは、新しいプロジェクトを作ってやると問題なく使えるので、
ネットから拝借したサンプルを切り貼りしたのが原因と思います。
新しいプロジェクトで作り直して使わせていただきます。
> Taskが使えないようです。
Task が使えるのは .NET Framework 4.5 からです。
もしくは Imports System.Threading.Tasks を削除しちゃったのでは?
新しいプロジェクトへ作業中の情報を入れようとして苦労しているところです。
Form1.vb、Form1.Designer.vbをそのままコピーしてもダメで、
テキストを編集してもエラーが消えずに困っています。
VBのバージョンは2016で、ターゲットフレームワークは.NET Framework 4.7.2にしています。
Imports System.Threading.Tasks をTaskが使えるプロジェクトのファイルで探してみましたが、
見つけることができません。どこにあればいいのでしょうか。
教えてください。
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
Task クラスのリファレンスに「定義」ってありますよね?
そこを見ると
名前空間:
System.Threading.Tasks
アセンブリ:
mscorlib.dll
となっています。
mscorelib.dll というのは、必ず参照されるアセンブリなので、無いはずがないのです。
エラーメッセージにはなんて書いてあるんでしょうか?
たくさん、ありがとうございます。
VB2019です、間違えました。
エラーというか、良いプロジェクトはTaskの色が変わりますが、
使えないほうは色が変わらず、Taskの下に赤い小波アンダーラインが出ます。
デバッグ開始すると、
: error BC30451: 'Task' は宣言されていません。アクセスできない保護レベルになっています。
が出ます。
試行錯誤の末にname.vbprojを替えるとTaskがサポートされることが分かり、
中を見ると <ItemGroup>に
<Import Include="System.Threading.Tasks" />
が無いことが分かりました。
ご指摘の通りだったと思います。
外したわけではないのですが、古いバージョンで作ったのを新しいバージョンで、
dataacqのアプリケーションの
ターゲットフレームワークを変更するだけではだめなんでしょうか。
これから教えていただいたように作り変えます。
「普通に書くと」
の方でうまく動いてくれました。(もう一つはまだ試していません)
何回か試しましたが誤動作は無かったです。
助かりました、本当にありがとうございます。
ツイート | ![]() |