• 締切済み

.NETの SerialPortクラスでデータ受信イベントを処理するには?

こんばんは。いつもお世話になっております。 Visual C++ 2005でSerialPortクラスを使ってシリアル通信をしたいのですが、データ受信イベントハンドラをどのように扱えばよいか分からず困っていますのでご教示ください。 HelpやMSDN、インターネット上で検索をして見つかるのはC#の例ばかりで、C++でどのように記述するのかが見つかりませんでした。 イベントやデリゲートなど、.NETで導入された(であろう)概念が出てきたり、^(ケット)記号が出てきたりと戸惑うことも多いのですが、きっと serialPort1->DataReceived += gcnew イベントハンドラを登録; // イベントハンドラの本体 private: System::Void serialPort1_DataReceived(System::Object^ sender, System::EventArgs^ e){ ほげほげ; } みたいな感じで書くのではないかと予想しています。 Visual Basic 6.0 でのシリアル通信はずっと使ってきました。 C/C++は使い始めて10年弱、C++/CLIは未経験です。(似て非なる言語?) よろしくお願いします。

みんなの回答

回答No.1

> serialPort1->DataReceived += gcnew イベントハンドラを登録; > > // イベントハンドラの本体 > private: System::Void serialPort1_DataReceived(System::Object^ sender, System::EventArgs^ e){ > ほげほげ; > } > > みたいな感じで書くのではないかと予想しています。 正解です。

Interest
質問者

補足

episteme様、回答ありがとうございます。 大分いいところまで行っていたのですね! ということで、気を取り直してコンパイラが吐き出すえらメッセージと格闘した末、 // イベントハンドラの登録 this->serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this, &Form1::serialPort1_DataReceived); // イベントハンドラの本体 private: System::Void serialPort1_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e){  try{    // richTextBox1->Text = "hoge";    // ↑ これはやっちゃいけないらしい。  }  catch(InvalidOperationException^ e){  }   catch(TimeoutException^ e){  }  catch(Exception^ e){  } } としたところ、コンパイルがとおり、データ受信時にはイベントハンドラが呼び出されることまで確認できました。(質問投稿時は、EventArgsの型が違っていてコンパイラに怒られていました。) しかし。データ受信イベントハンドラは別スレッドで動いているようで、1行コメントアウトしてある部分を使おうとすると、InvalidOperationException が発生してしまいます。受信したデータをフォームに渡すにはどうしたらいいでしょうか?

関連するQ&A

  • VS.NET2005 C#にてSerialPort受信されたときのイベントについて質問

    Visual Studio.NET2005ProにてSerialPort接続アプリケーションを開発しております。 受信が来たときのイベント DataReceived のところで、受信された文字列をテキストボックスへ表示させるということを行いたいのですが、エラーが出てしまいます。 ちなみにプログラムはこうです。 private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { //シリアルポートからデータを受信するたびに発生する textBox_all_in.Text = (string)serialPort.ReadByte(); } それで、エラーは エラー 1 型 'int' を型 'string' に変換できません。 このように出てしまいました。プログラミング初心者で、つまずいてしまいどうすればよいのかわからなく困っております。アドバイスよろしくお願いします。

  • SerialPortのDataReceivedイベントについて

    Visial Basic 2005 にて SerialPort コンポーネントを使ったアプリを作っています。 当初、Microsoft のサンプルを参考に SerialPort1.ReadLine でデータを受信していたのですが、この方法だとバッファ内から再度同じデータを受信してしまうらしく、新しいバッファからデータを受信しないとイベントが発生する毎に古いデータを読み取ってしまいます。 そこで調べていたところ、Microsoft のフォーラムで以下のような Visual C# のソースを見つけました。 (以下引用) > if (serialPort1.BytesToRead > 0) > { > // 受信バッファからデータを取得 > byte[] b = new byte[serialPort1.BytesToRead]; > Read(b, 0, b.Length); > } まだ Visial Basic 初心者なもので Byte 型の扱い方や上記ソースは Visial Basic でどのように書けばよいのかわかりません。 どなたかご教授ください。 よろしくお願いいたします。

  • イベントハンドラ関数について

    現在VC++/CLR 2005 でプログラミングをしています。 基本的な事柄かもしれませんが、質問させてください  以下の2つのボタンのイベントハンドラ関数があった場合 //ボタン1のイベントハンドラ関数 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) String^ str = textBox1->Text } //ボタン2のイベントハンドラ関数 private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { } ボタン2をクリックしたときの動作とボタン1の動作を同じにしたいと思っています。 その場合は private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) String^ str = textBox1->Text } //ボタン2のイベントハンドラ関数 private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { String^ str = textBox1->Text } のようにボタン2のイベントハンドラ関数をボタン1と同じように書けばいいのですが イベントハンドラ関数の処理が膨大になった場合を考えて省略する 書き方は無いのでしょうか?(以下の場合ですとエラーが起こってしまいます。) private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { button1_Click(); } 宜しくお願いします

  • 実行時にコントロールのイベントの登録/解除を、イベントハンドラのメソッドをあらかじめ知っていないロジックから実施する方法

    実行時にコントロールのイベントの登録/解除を、イベントハンドラのメソッドをあらかじめ知っていないロジックから実施する方法 通常、実行時にコントロールにイベントの登録/解除 を行う際は。 AddHandler 対象コントロール.イベント名, AddressOf メソッド RemoveHandler 対象コントロール.イベント名, AddressOf メソッド や AddHandler 対象コントロール.イベント名, メソッドのデリゲート型 RemoveHandler 対象コントロール.イベント名, メソッドのデリゲート型 を行うと思います。 しかし、この方法では、これを実施するロジックが AddressOf メソッド や メソッドのデリゲート型 を知っていなければなりません。 そうではなく、それをあらかじめ、知っていなくても 対象コントロール から AddressOf メソッド や メソッドのデリゲート型 に該当するオブジェクトを取得するなどして、 実施できる方法を教えてください。 言語は、.NET系であれば。。 VB.NET, C#, C++のいづれかでもよいです。 できさえすればよいです。 J#とか、Delphi.NETとかマイナーなのは、厳しいです。 なお、C++でもしできるのであれば。 2003のマネージC++と、 2005のC++/CLIの両方について知りたいです。 以上、よろしくお願いします。

  • SerialPort処理でInvokeメソッドを使用するとエラーが発生。

    はじめまして。こんばんわ。 同一プロジェクトの複数のフォームから、RS232C接続処理を行っております。 まったく同じ処理内容なので、クラスを使用しようとしております。 しかし、データ受信時、Invokeメソッドを使用して、各フォームのイベントをCALLしますと、『InvalidOperationException』が発生し、『ウィンドウ ハンドルが作成される前、コントロールで Invoke または BeginInvoke を呼び出せません。』というエラーメッセージが表示されてしまいます。 ソースを下記に記載いたします。どなたか、原因・対処方法がわかる方がいらっしゃいましたら、御手数をおかけいたしますが、ご教示の程、よろしくお願い申し上げます。 ============================== 呼び出し元フォーム ============================== Public Class Form1   Private cls232CIns As cls232C   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click     cls232CIns.openport()   End Sub   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load     cls232CIns = New cls232C()   End Sub   Public Sub DispData(ByVal data As String)     TextBox1.Text = data   End Sub End Class ============================== SerialPort通信クラス ============================== Imports System.IO.Ports Public Class cls232C   WithEvents SP1 As SerialPort   Delegate Sub RecvDataDisp(ByVal dataR As String)   Public Sub New()     SP1 = New SerialPort("COM6", 9600)   End Sub   Public Sub openport()     SP1.Open()   End Sub   Public Sub closeport()     SP1.Close()   End Sub   Public Sub ReceiveData(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived     Dim getdata As String     getdata = SP1.ReadLine     Form1.Invoke(New RecvDataDisp(AddressOf Form1.DispData), getdata) ←ここでエラー発生   End Sub End Class  

  • C#にイベントハンドラ(object sender, EventArg

    C#にイベントハンドラ(object sender, EventArgs e) に引数を追加して、 イベントハンドラに値を渡したいのですが、 どのように記述したらいいのでしょうか?

  • eventの概念が理解できません

    こんにちは。オブジェクト志向でVB、C#を学んでいます。デリゲートを理解してeventについて学んでいますが、よく理解できません。 イベントとは、「あるアクションが発生したことを自動的に通知するための仕組み」と本にあります。 さらに、「送信側オブジェクトのイベント(と呼ばれるクラスメンバーに、受信側のイベントハンドラー(と呼ばれるメソッド)を登録します。」とあります。 下記が本に載っているコードです。 私が理解できているのは、 ・戻り値が無し、引数をとらないメソッドを参照するオブジェクト。MyEventHandlerというデリゲートを宣言 ・戻り値が無し、引数をとらないメソッドを参照するオブジェクト。SomeEvent変数を宣言 ・MyEvent型のevt変数の宣言 理解できないのは、 evt.SomeEvent += Handler;。何をやっているかわかりません。 ここをわかりやすくお教え頂けませんでしょうか? using System; //MyEventHandler型を宣言。ここは理解できます。 delegate void MyEventHandler(); class MyEvent{ //イベントの宣言。EventHandler型の変数、SomeEvent。 public event MyEventHandler SomeEvent; public void Fire(){ if(SomeEvent !=null) SomeEvent(); } } class EventDemo{ static void Handler(){ //←イベントハンドラー Console.WriteLine("Event occurred"); } static void Main(){ MyEvent evt = new MyEvent(); evt.SomeEvent += Handler; evt.Fire(); } } また、もう一点お教え下さい。フォーム上のボタンをクリックした時に、メッセージを表示するようなイベントはどのような形で動いているのでしょうか? senderはイベントの発生元のオブジェクトがそのまま入っていて、eはイベントの補足情報が入っているのは理解しました。 ボタンをクリックした時に、ボタンクラスから何らかの情報が送られてきて、それをsenderとeで受取ると思うのですが、これのどこにeventとデリゲートが関わってくるのでしょうか? 何かモヤモヤしてeventがわかりません。 宜しくお願い致します。 private void btn_Click(object sender, EventArgs e) { messagebox.show("hello"); }

  • VB.NET スレッドからのイベント受信について

    はじめて質問させていただく、VB.NET初心者です。 ただいまスレッド、イベント処理を作成中で Form1にButton1、Label1を貼り付け以下の様なプログラムを記述しました。 (スレッドにて5秒ごとにイベントを発生させます。) 'イベント引数 Public Class EventArgs Inherits System.EventArgs Public nowTime As String End Class 'イベント発行 Public Class EventTest Public Event _event(ByVal sender As Object, ByVal e As EventArgs) Public Sub Go() Dim args As New EventArgs() args.nowTime = Now.ToString RaiseEvent _event(Me, args) End Sub End Class 'フォーム内処理 'スレッド宣言 Dim MyThread As New System.Threading.Thread(AddressOf _Thread) Private WithEvents _test As New EventTest() 'イベント受信   Private Sub Handler(ByVal sender As System.Object, ByVal e As EventArgs) Handles _test._event Label1.Text = e.nowTime End Sub 'スレッド(5秒間隔でイベント発行) Private Sub _Thread() Dim i As Integer For i = 0 To 99 System.Threading.Thread.Sleep(5000) _test.Go() Next End Sub 'スレッド起動 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click MyThread.Start() End Sub End Class 開発環境から普通に実行すれば正常に動作している様なのですが、 イベント受信部(Handler)のLabel1.Text = e.nowTime部に ブレークポイントを置いてLabel1のウォッチをするとその時点で 処理がとまってしまいます。なぜとまるのかが知りたいです。 作成方法がまずいのでしょうか? 皆様よろしくお願いいたします。

  • デリゲートとイベントの関係(VB.NET2005)

    VB2005の本に書いてある内容が理解できません。 誰か助けてください! ---------- イベントとデリゲートの仕組み  .NETイベントが内部ではデリゲートとして処理されることを理解すれば、その威力を存分に引き出すことができます。 もう少し厳密に言うと、イベントを発行するクラスには、そのイベントをサブスクライブするクライアントすべてをポイントする、プライベートデリゲートフィールドが定義されています。 イベントが発行されると、.NETのイベントインフラストラクチャによって該当するデリゲートフィールドのInvokeメソッドが呼び出されます。そして、Invokeメソッドからすべてのクライアントにイベントが通知されます。  このことは、.NET Frameworkで定義されているイベントごとに対応するデリゲートが存在することからもうかがい知ることができます。 [オブジェクトブラウザ]を使用すれば、それを確認できます。 たとえば、第2引数としてEventArgsオブジェクトを受け取るイベントはすべて、内部ではSystem.EventHandlerデリゲートを通じて管理されます。 ほとんどのWindowsフォームコントロールが公開するKeyPressイベントは、KeyPressEventHandlerデリゲートによって処理されますが、このデリゲートは、第1引数としてObject、第2引数としてKeyPressEventArgsオブジェクトを受け取るSubプロシージャをポイントします。 ---------- 全体的にちんぷんかんぷんですが特に「サブスクライブ」などがわかりません よろしくお願いします。

  • C# シリアル通信でデータ受信時の欠損について

    Visualstudio 2013 を使用して C# で開発を行っています。 SerialPort Classを使用してデータの送受信をするプログラムを作成しているのですが、 非同期でデータを受信する際にどうしてもうまくデータを取得出来ません。 5Byteのデータは正常に取得できるのですが、 その直後にくる40Byteのデータは、真ん中あたりの10数Byteや最後の10数Byteしか取れません。 serialPort.DataReceived に登録したイベント関数の中身です。 -------------------------------------------------------------------------------------- private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { bytesRead = 0; // Initialize a buffer to hold the received data byte[] buffer = new byte[this.serialPort.ReadBufferSize]; try { bytesRead = this.serialPort.Read(buffer, 0, buffer.Length); if (true == serialPort.IsOpen) { serialPort.DiscardInBuffer();//受信バッファをクリアする } } catch (Exception ex) { DataLog.Exception(ex); } //派生クラス用の処理 DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead); DeviceClassEvent(this, _DeviceClassEventArgs); } -------------------------------------------------------------------------------------- ネットの情報を参考に、 ReceivedBytesThreshold の値を期待するデータ量に逐一変えることで とりあえず正常に取ることが出来たのですが、これでいいのでしょうか? 期待するデータ量がわからなかった場合は使えないのかなとも思います。 データが欠損してしまう理由、 上記の対処法以外の一般的な対処法など有りましたら教えて下さい。 その他参考になるページ等ありましたら教えていただけると大変助かります。

専門家に質問してみよう