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

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

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

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

VB.NET

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

Q&A

解決済

5回答

2588閲覧

DoEventsを使用せずにDoLoopを抜ける方法

SPRK

総合スコア1

VB

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

VB.NET

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

0グッド

0クリップ

投稿2020/06/10 00:16

vb.netを使用してTcpClientの作成をしています。
データ送信ボタンを押すと、切断ボタンが押されるまでデータをループで送り続ける使用になっています。
Application.DoEvents()
If flg = true Then Exit Do
上記でDoLoopを抜けていたのですが、DoEventsの処理を使ってはいけないと言われました。
そのため、非同期処理 async/await を使用しようと思いましたが上手く実装できませんでした。
どのようにすれば私の思う事を実装できるか、DoEventsは本当に不必要なのか、
async/awaitで実現できるのか、教えて頂けませんでしょうか。

以下現在のソースです

Public Class Form1 Private m_tcp As System.Net.Sockets.TcpClient Private flg As Boolean Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click Dim IP As String Dim Port As Integer IP = TextBox1.Text Port = Integer.Parse(TextBox2.Text) m_tcp = New System.Net.Sockets.TcpClient(IP, Port) Console.WriteLine("サーバー({0}:{1})と接続しました({2}:{3})。", _ DirectCast(m_tcp.Client.RemoteEndPoint, System.Net.IPEndPoint).Address, _ DirectCast(m_tcp.Client.RemoteEndPoint, System.Net.IPEndPoint).Port, _ DirectCast(m_tcp.Client.LocalEndPoint, System.Net.IPEndPoint).Address, _ DirectCast(m_tcp.Client.LocalEndPoint, System.Net.IPEndPoint).Port) End Sub Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click If m_tcp Is Nothing Then Exit Sub End If Console.WriteLine("送信開始") Dim ns As System.Net.Sockets.NetworkStream = m_tcp.GetStream() ns.ReadTimeout = 10000 ns.WriteTimeout = 10000 Dim text As Long Dim bytedata() As Byte flg = False Do Dim sendBytes(49) As Byte              ーーー配列の処理ーーー ns.Write(sendBytes, 0, sendBytes.Length) Dim i As Integer For i = 0 To 119 Console.Write(sendBytes(i) & ", ") Next i Dim textFile As System.IO.StreamWriter textFile = New System.IO.StreamWriter("C:\Users\G570\Desktop\Tcp\TcpClient\6月8日\log.txt", True, System.Text.Encoding.Default) For i = 0 To 119 textFile.Write(sendBytes(i) & ", ") Next i textFile.WriteLine() textFile.Close() Array.Clear(sendBytes, 0, sendBytes.Length) System.Threading.Thread.Sleep(5000) Application.DoEvents() If flg = True Then Exit Do Loop End Sub Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click flg = True m_tcp.Close() Console.WriteLine("切断しました。") End Sub

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

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

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

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

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

maisumakun

2020/06/10 00:33

「DoEventsの処理を使ってはいけない」理由は確認しましたか?
guest

回答5

0

  1. 送信処理をメソッド化し、Task.RunでCancellationTokenを渡して起動(送信スレッドとする)
  2. UIスレッドの切断ボタンクリックでCancellationTokenSource.Cancelを実行
  3. 送信スレッドの送信ループ処理をしている所でCancellationToken.IsCancellationRequestedをチェックさせて中断

で中断が実現できると思います。DoEventsは想定外のタイミングでウィンドウメッセージが処理され、フォームイベントが実行されて処理が追いづらくなるので、私は基本的に使わないですね。

vaguely -【C#】Taskをキャンセルする

回答してる間に、YAmaGNZさんと回答が被ってしまいました。YAmaGNZさんのサンプルソースが参考になると思います。

投稿2020/06/10 01:07

編集2020/06/10 01:12
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

SPRK

2020/06/10 08:49

回答ありがとうございます。 正直、サンプルソースでは何を行っているか分からなかったため、処理の説明は大変助かります! サンプルソースをベースに考えてみます。
guest

0

ベストアンサー

下記のような感じですかね?
実際には処理中に再度ボタンが押されたなどの考慮が必要になってくるとは思います。

VBNET

1Private cts As CancellationTokenSource 2 3Private Async Sub Button1_Click(sender As Object, e As EventArgs) 4 5 cts = New CancellationTokenSource 6 7 Await Task.Run(Sub() 8 While cts.IsCancellationRequested = False 9 Console.WriteLine($"{Now:HH:mm:ss.fff}") 10 Thread.Sleep(100) 11 End While 12 End Sub) 13 14End Sub 15 16Private Sub Button2_Click(sender As Object, e As EventArgs) 17 cts.Cancel() 18End Sub 19

一定間隔でデータを送信するだけみたいですので、タイマーでdo~loopの中身だけ処理するのも手だと思います。

投稿2020/06/10 01:06

編集2020/06/10 01:44
YAmaGNZ

総合スコア10489

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

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

SPRK

2020/06/10 08:44

回答ありがとうございます。 つまり、DoLoopは使用しなくて良いという事でしょうか? ソースを参考に考えてみます!
guest

0

Timerが一番楽だと思います。
Button2_ClickでTimerに繰り返し時間セットしONにて開始。データ送信開始で繰り返し実行。
Button3_ClickでTimerをOFFへセット。Timerストップで終わり。

訂正:
Application.DoEvents()は使わないとダメかもしれません。やってみないと分かりません。
指摘されたのは、Sleepの方と言うことはないでしょうか?

投稿2020/06/10 00:56

編集2020/06/10 01:25
tosi

総合スコア553

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

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

SPRK

2020/06/10 08:41

回答ありがとうございます。 Timerは発想にありませんでした。 指摘されたのはDoEventsのみで、Sleepは何も言われてないです。 Sleepだと問題があるのでしょうか?
tosi

2020/06/11 00:01 編集

プログラムを見ますと、 Button2_Clickで繰り返しのバッチが動きます。 この繰返しをButton3_Clickで途中停止させる感じに見えます。 1バッチ処理+Sleep中はホールド状態となり、Button3_Clickからの入力は受付けできません。 DoEvents()にてForm側へ制御が移りButton3_Clickの入力が可能となります。 しかしながら、次のバッチが動いてしまう為に、Button3_Clickの入力可能は僅かな時間しかありません。その一瞬を狙ってクリックすれば止まりますが、運用的には厳しいです。 運用を考えればSleep(5000)の5秒間は、Button3_Clickが押せる状態として、人からの停止指示の判断を待つ様にする方が良いと思われます。 そのため、ホールドになるSleep(5000)ではなく、1バッチ終了後の5秒間は、別の方法で停止させてクリック入力が出来るようにする指示を受けたのではないかと想像致しました。
guest

0

以下参考
時間のかかる処理の進行状況を表示する
バックグラウンド処理を途中でキャンセルするには?[2.0のみ、C#、VB]

DoEventsによる技法は、.NET Frameworkでマルチスレッドプログラミングがサポートされる以前の技法です。
苦肉の策より、サポートされる機能を利用する方が、影響が少なくて済みます。

投稿2020/06/10 00:31

編集2020/06/10 01:06
sazi

総合スコア25327

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

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

SPRK

2020/06/10 08:37

回答ありがとうございます。 DoEventsがサポート以前の技法とは知りませんでした。 サポートされる機能を利用する方が、影響が少ないなど、その辺をちゃんと調べます。
sazi

2020/06/10 08:53

提供される機能を利用している分には、その機能に変更があってもそれは提供側でカバーしてくれますが、そうでない場合は影響が無いとは言い切れませんので。
guest

0

スレッド化でしょうね。
Button2_Clickイベントのタイミングで、今Button2_Click内で行っている処理をスレッドで起動して抜ける。
それだけでいいはず。
問題はVBAでのスレッド化の難易度ですね。
私はやったことがないですが、ググれば参考になりそうなサイトはあるみたいなので、調べてみてください。

投稿2020/06/10 00:26

ttyp03

総合スコア17000

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

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

SPRK

2020/06/10 08:31

回答ありがとうございます。 スレッド化ですか… 一度調べてみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問