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

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

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

3回答

10177閲覧

C# シリアル通信 データ受信待ち

miyabin09

総合スコア9

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2020/01/27 09:53

前提・実現したいこと

VisualStudioでRS232Cでシリアル通信を行うプログラムを作成しております。
COMポートの接続・送信・受信自体は問題が無い状態で、同様のプログラムを入れたパソコンで動作を確認済みです。
実現したいことが、serialportで送信→受信待ち→受信したら送信を行いたいです。

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

serialportメソッドのwritelineで送信しておりまして、受信待ちがうまくいっておりません。
while文で受信データボックスが空で無い間は、待機という考えなのですがどうにも待機せずに
送信されてしまいます。
理想:1回目のデータ送信→受信ボックスにデータが来る→自動でxxxデータを送る
現状:1回目のデータ送信→xxxデータを送ってしまう

該当のソースコード

ソースコード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) { serialPort1.Encoding = Encoding.ASCII; } private void sendButton_Click(object sender, EventArgs e) { //シリアルポートがオープンしていない場合、処理しない if(serialPort1.IsOpen==false) { return; } //受信データボックスを空にする// rcvText.Text = ""; //テキストボックスからデータを取り出す String data = sndText.Text; //送信データがない場合、データを送信しない if(string.IsNullOrEmpty(data) ==true) { return; } try { //シリアルポートからデータ送信 data = data + "\r"; serialPort1.WriteLine(data); //受信データがくるまで待機// while (rcvText.Text != "") ; //2回目のデータ送信// string xxx = "xxx"; serialPort1.WriteLine(xxx); //送信データテキストボックスクリア sndText.Clear(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void readButton_Click(object sender, EventArgs e) { if(serialPort1.IsOpen == true) { //シリアルポートをクローズする! serialPort1.Close(); //切断ボタンを xxxx 表示に変える! exitButton.Text = "xxxx"; } else { //オープンするシリアルポートをテキストボックスから取り出す! serialPort1.PortName = comPort.Text; try { //シリアルポートをオープンにする serialPort1.Open(); //ボタンの表示を変更 exitButton.Text = "切断"; readButton.Text = "xxxx"; } catch (Exception ex) { MessageBox.Show(ex.Message); } } } private void exitButton_Click(object sender, EventArgs e) { //シリアルポートをクローズ serialPort1.Close(); //ボタン表示の変更 exitButton.Text = "xxxx"; readButton.Text = "接続"; } private void deleteButton_Click(object sender, EventArgs e) { //受信データのクリア rcvText.Text = ""; } private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { //シリアルポートがオープンしていない場合、処理をなし if(serialPort1.IsOpen==false) { return; } try { //受信データの読み込み string data = serialPort1.ReadLine(); data = data +"\r"; if (!string.IsNullOrEmpty(data)) { Invoke((MethodInvoker)(() => rcvText.AppendText(data))); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } }

}

試したこと

while (rcvText.Text != "") ;
で受信データ待機が出来ていない

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

Visual Studio 2015

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

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

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

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

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

guest

回答3

0

自己解決

理屈はなんか分かりませんけど、自己解決しました。
while (rcvText.Text != "")  ozwkさんの言う通りで、空じゃない間繰り返す→空なら抜ける
もともと空になっていたので、すり抜けている。(意味がない)

while (rcvText.Text == "") 空の間で繰り返す→データが入ったのなら、抜ける
意味合いはあっているけどフリーズ

serialport.readlineからのテキストボックス(rcv.Text)への出力という流れなので
イベントを変更
while (serialPort1. ReadLine() == "") ;へ変更したらなんかうまくいった。

serialportの受信イベントで無いとうまくいかないのかな?
詳しいひといましたら解説お願いします。

投稿2020/01/27 11:44

miyabin09

総合スコア9

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

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

YAmaGNZ

2020/01/27 12:04 編集

>while (rcvText.Text == "") 空の間で繰り返す→データが入ったのなら、抜ける >意味合いはあっているけどフリーズ この場合は、whileでループしているが、イベントを処理する暇がないのでハード的にデータを受信していてもDataReceivedイベントが処理されない状態になっています。
miyabin09

2020/01/27 12:09

理屈は分かりました。ありがとうございます。 NewLine待ちで止まっているだけだと、while文と合わせると処理としてはどうなんでしょうか? 2重で処理していて、イマイチなのかなという感じがします。 もっと早く処理する方法はあるでしょうか?
YAmaGNZ

2020/01/27 12:36

はっきり言って while(serialPort1. ReadLine() == ""); と書く意味はありません。 どのようなプロトコルなのか分かりませんが、 string res = serialPort1. ReadLine(); と書いた方が受信したデータを取得し判断できるので良いのではないでしょうか? 速度に関しては現状上がっている書き方はどれも変わらないでしょう。
YAmaGNZ

2020/01/27 12:38

今提示されている方法はUIスレッドが停止するので、それが嫌だというのであれば送受信処理をTaskで非同期処理にするなりするべきでしょう。
miyabin09

2020/01/28 10:37

丁寧説明していただきありがとうございました。
guest

0

while (rcvText.Text != "") ; // 空文字列じゃなければ繰り返す = 空文字列になったら抜ける

投稿2020/01/27 10:10

ozwk

総合スコア13521

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

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

miyabin09

2020/01/27 10:32

空にしていたので、すぐにすり抜けていたのですね。 serialportの受信待機について、何か良い方法はないでしょうか?
ozwk

2020/01/27 10:44

受信データが来るまで待機って言っておきながら実際は逆のことやっとるぞって話です
miyabin09

2020/01/27 10:45

while (rcvText.Text == "") ;  これだと待機はするんですが、フリーズしている状態です モニターで返信しても反応が無いです。
退会済みユーザー

退会済みユーザー

2020/01/27 12:05

これおかしいとは思ったもののあんまりにもハッキリと質問文に書いてあったから特殊な待ち方してるんだろうと思ってたのですが本当に間違ってたんですね・・・。
guest

0

最適化が働いて条件式自体が無視されているのでvolatileを使いましょう
bool変数とかで判定するように↓方が良いかと

投稿2020/01/27 10:04

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

miyabin09

2020/01/27 10:34

空になっていたので、すぐにすり抜けいました。 serialportの受信待機に何か良い方法はありませんでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問