VB2010で、シリアル通信の方法を教えてください。

ツールボックスの「Serial Port」を使っています。
送信までは難なくできたのですが、受信が旨くいきません。
参考にしたサイトは、
http://msdn.microsoft.com/ja-jp/library/cc720852 … です。

これを実行すると、受信が出来ないだけでなく、フリーズしてしまいます。

どうやったら、受信できるのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (4件)

受信データが、


STX(&H02)とETX(&H03)には挟まれた形式のテキスト文字になっている。
エラーチェックのBCCは付加されない。
という仕様ならば
ポートをOpenした直後に
SerialPort1.NewLine = Chr(3)
とすれば良い。
受信したデータの先頭1文字がSTXの場合に正常なデータと判断できます。
    • good
    • 0
この回答へのお礼

ありがとうございます!

成る程、そのようにすれば良いですね。

お礼日時:2010/06/11 19:05

>受信するデータの終端の仕様が、ETX(&h02)でした。



NewLine プロパティにChr(2)を入れたらどうですか?
    • good
    • 0
この回答へのお礼

御解答、ありがとうございます。

>NewLine プロパティにChr(2)を入れたらどうですか?
改行コードの代わりになるものを、追加できるということですよね。

何処で、宣言をしたら良いですか?
また、参考になりそうなサイトを教えてください。

よろしくお願いします。

お礼日時:2010/06/10 18:55

どのようなデータを受信しているのでしょうか?



ReadLine()メソッドのヘルプを見ると
『入力バッファ内の NewLine 値まで読み取ります。
既定では、ReadLine メソッドは行を受け取るまでブロックします。
この動作が不適切な場合は、ReadTimeout プロパティに 0 以外の値を設定して、ポート上に行が存在しない場合は ReadLine メソッドで強制的に TimeoutException がスローされるようにします。』

となっていて、なおかつ NewLine の既定値はラインフィード(CTRL+J)なので
受信するデータにラインフィード(CTRL+J)が含まれていない場合には戻ってきません。

受信するデータの終端がキャリッジリタン(CTRL+M)なら
NewLineプロパティにChar(13)を設定してみてください。

参考URL:http://www.robotsfx.com/robot/robohow/RoboHow60/ …
    • good
    • 0
この回答へのお礼

御解答を戴きまして、ありがとうございます。

>NewLineプロパティにChar(13)を設定してみてください。
これが、原因のようです。
受信するデータの終端の仕様が、ETX(&h02)でした。

こうなると、面倒でも、一文字ずつ受信させるしかなさそうですね。

お礼日時:2010/06/10 08:40

・ハイパーターミナルで受信できるかテストしてみる


 →できない場合はCOMポートの設定がおかしいか、
  パーソナルファイアーウォールの設定を見てみる
  ※特定IPアドレスからの送信ならブロックしないようにする

・COMポートの設定を見直す
 CPR managerとかでポートを作り、テストしてみる

・Serial Portの通信設定のプロパティを見直す

・SerialPort1.ReadLine
 をReadExistingに変えてみる
とかでしょうか?

参考URL:http://social.msdn.microsoft.com/Forums/ja-JP/vb …
    • good
    • 0
この回答へのお礼

御解答を戴きまして、ありがとうございます。

ReadExistingで返事が返ってきました。
ただ、送られた通信プロトコルが分離されて受信しているようです。
(2度の受信イベントで、通信プロトコルが成立する)

お礼日時:2010/06/10 08:31

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

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

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 の値を期待するデータ量に逐一変えることで
とりあえず正常に取ることが出来たのですが、これでいいのでしょうか?
期待するデータ量がわからなかった場合は使えないのかなとも思います。

データが欠損してしまう理由、
上記の対処法以外の一般的な対処法など有りましたら教えて下さい。

その他参考になるページ等ありましたら教えていただけると大変助かります。

Visualstudio 2013 を使用して C# で開発を行っています。

SerialPort Classを使用してデータの送受信をするプログラムを作成しているのですが、
非同期でデータを受信する際にどうしてもうまくデータを取得出来ません。

5Byteのデータは正常に取得できるのですが、
その直後にくる40Byteのデータは、真ん中あたりの10数Byteや最後の10数Byteしか取れません。


serialPort.DataReceived に登録したイベント関数の中身です。

-------------------------------------------------------------------------------...続きを読む

Aベストアンサー

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();//受信バッファをクリアする
    //}

    // 受信バッファにデータがなくなるまで繰り返し読込む
    while (true)
    {
      if (0 == serialPort.BytesToRead)
      {
        break;
      }
      buffer[bytesRead] = (byte)serialPort.ReadByte();
      bytesRead++;
      System.Threading.Thread.Sleep(0);

      // シリアルポートの受信バッファには、
      // ・必要なブロックの途中から受信している。
      // ・次のブロックの先頭部分も受信されている。
      // 可能性があるので、ここで必要なブロックだけRead()できたことを確認する。
      if (必要なブロックが正常に読めたか確認する関数())
      {
        break;
      }
    }
  }
  catch (Exception ex)
  {
    DataLog.Exception(ex);
  }

  //派生クラス用の処理
  DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead);
  DeviceClassEvent(this, _DeviceClassEventArgs);
}

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.Le...続きを読む

Qシリアル通信におけるバイトデータの送受信(VB.NET)

Visual Basic .NETで、WriteLine("テキスト")やReadLineを使えば、テキストデータは送受信できますが、バイトデータはどのようにすれば送受信できるのでしょうか?具体的なコードを知っている方がいたら教えて頂きたいです。

Aベストアンサー

こんにちは
http://msdn2.microsoft.com/ja-jp/library/ms143551(VS.80).aspx

そこまでご存知でしたらあともうひと調べでしたね。

QVB.netで、シリアル通信のタイムアウト処理について

VB.netで、シリアル通信のタイムアウト処理について

http://msdn.microsoft.com/ja-jp/library/7ya7y41k.aspx
このサイトのコードを、参考にしています。
------------------------------------ここから
Dim com1 As IO.Ports.SerialPort = Nothing
Try
com1 = My.Computer.Ports.OpenSerialPort("COM1")
com1.ReadTimeout = 10000

Catch ex As TimeoutException
returnStr = "Error: Serial Port read timed out."
Finally
If com1 IsNot Nothing Then com1.Close()
End Try

------------------------------------ここまで

この方法ですと、タイムアウトが発生したらポートを閉じるようですが、これを、送信したシリアルのデータを再度、送信させたいと思います。
そして、何度かリトライを掛けた後に、やっぱり駄目だったときに
ポートを閉じたいと思います。

どんな方法がありますか?

参考になりそうなサイトなどがありましたら、教えていただけませんか。
以上、よろしくお願いします。

VB.netで、シリアル通信のタイムアウト処理について

http://msdn.microsoft.com/ja-jp/library/7ya7y41k.aspx
このサイトのコードを、参考にしています。
------------------------------------ここから
Dim com1 As IO.Ports.SerialPort = Nothing
Try
com1 = My.Computer.Ports.OpenSerialPort("COM1")
com1.ReadTimeout = 10000

Catch ex As TimeoutException
returnStr = "Error: Serial Port read timed out."
Finally
If com1 IsNot Nothing Then com1.Close()
End Try

----------------...続きを読む

Aベストアンサー

タイムアウトはWrite/Read(送受信)系メソッドで
発生します。そのメソッドをTry~Catchブロックで
ハンドリングしないと意味ないでしょ。
掲題のプログラムはポートを開いて、タイムアウトの
時間を設定しただけですから、送受信していません。

QVisual Basic 2010を使ってRS-232Cとの通信をした

Visual Basic 2010を使ってRS-232Cとの通信をしたい。

現在、機器とPCとの通信のやりとりをするため、機器のマニュアルを見ながら悪戦苦闘しています。

通信のやり取りについては、マニュアルにVB6を使った例が書いてあります。
しかしVB6が手に入らなかったので、Visual Basic2010を現在使っています。

マニュアル(VB6向け)には
・On the Project Menu, click Components to bring up a list of additional controls available in VB6.
・Scroll through the controls and select Microsoft Comm Control 6.0. Select OK. In the toolbar at the left of the screen, the Comm Control will have appeared as a telephone icon.
・Select the Comm control and add it to the form
と書いてあります。

よく分らなかったのですが、上のメニューの「Project」⇒「Add reference」を選び、「COM」の中にあった「Microsoft Comm Control」を選びました。

が、左のツールバーには電話のアイコンは出てきませんでした。

2010の場合、VB6と違って別のやり方をしないといけないのでしょうか?


ご存知の方がいましたら、教えて頂きたいです。よろしくお願いします。

Visual Basic 2010を使ってRS-232Cとの通信をしたい。

現在、機器とPCとの通信のやりとりをするため、機器のマニュアルを見ながら悪戦苦闘しています。

通信のやり取りについては、マニュアルにVB6を使った例が書いてあります。
しかしVB6が手に入らなかったので、Visual Basic2010を現在使っています。

マニュアル(VB6向け)には
・On the Project Menu, click Components to bring up a list of additional controls available in VB6.
・Scroll through the controls and select Microsoft Comm Control 6.0...続きを読む

Aベストアンサー

SerialPortコンポーネントでシリアル通信が可能です

VB6にはMSCommというコンポーネントがあったようですが、.NET2003以降にはありません。
2005からSerialPortコンポーネントが標準でついているはずなのでそちらを使用してはいかがでしょうか?

http://msdn.microsoft.com/ja-jp/library/cc825644.aspx

QVisual Basic でのコードをASCII変換、16進変換したものを元に戻す方法を教えてください

string(9)のエリア"Aa1アあa "の文字を1文字ずつASCII変換して、16進変換し、string(18)のエリアに格納します
すると"416131B182A08281202020"と変換されます
(一文字ずつ Hex(Asc(Buf))を使用しました)

逆に、"416131B182A08281202020"を"Aa1アあa "に戻したいのですが、
どのような関数を使えばよいのかわかりません。
困っています。教えてください。よろしくお願いいたします。

Aベストアンサー

VB既存の関数ではできないと思うので、自分で関数を作るなりしてください。

ヒントです。
ASC関数により変換された2バイト文字(シフトJIS)の1バイト目は81~9FおよびE0~FC(すべて16進)になります。
16進数から10進数に戻すには、頭に"&H"をつけます。(&H82A0 = 「あ」のシフトJISコード)
文字を数字に変換するのはVal関数、数字(文字コード)から文字に変換するのはChr関数です。

QC#にてCTI。RS232Cの受信と送信について。

C#でCTI機能の実現を目指しております。
プログラムは以下サイトからDLして改造しています。
http://tmp.junkbox.info/e14.html
しかし、エラーが頻発し原因不明です。

構成、仕様としては、
アロハPC1という機械から電話番号データを受信しPCに受け渡し。
・データを受け取る(ここは問題なし)
データ形式は
STX(02H)、着信日時(月日曜時分9桁)、電話番号(20桁)、ETX(03H)
として送られてきます。
例) 1214112050457771111
・正常データの場合はACK(06H)を返信(これをしない場合1秒後に同データが再送される)
・データ整形
・データ表示
というような形にしたいのです。

上記サイトのプログラムをアロハPC1に合わせて通信できるようにした状態ですと、例のような生データが問題なく表示されます。
これを以下のようにしてみましたが、エラーが出てしまいます。
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
// 受信文字列の取得
string receivedData = "";
string moji = "";
string moji2 = "";
try
{
receivedData = this.serialPort1.ReadExisting();
receivedData = receivedData.Replace(this.serialPort1.NewLine, "\r\n");

string[] week = { "(日)", "(月)", "(火)", "(水)", "(木)", "(金)", "(土)" };

string stx = receivedData.Substring(0, 1);
string etx = receivedData.Substring(30, 1);

// ACKを返す。
byte[] ack_data = new byte[1];
ack_data[0] = 06;
serialPort1.Write(ack_data,0,1);

string data_m = receivedData.Substring(1, 2);
string data_d = receivedData.Substring(3, 2);
string w = receivedData.Substring(5, 1);
int w2 = int.Parse(w);
string data_w = week[w2];
string data_h = receivedData.Substring(6, 2);
string data_i = receivedData.Substring(8, 2);

moji2 = receivedData.Substring(10, 20);
// スペースを痴漢
moji2 = moji2.Replace(" ", "");

moji = data_m + "月" + data_d + "日" + data_w + data_h + "時" + data_i + "分 ";
if (moji2 == "P")
{
moji = moji + "着信番号非通知\n";
}
else if (moji2 == "O")
{
moji = moji + "着信番号提供地域外\n";
}
else if (moji2 == "C")
{
moji = moji + "公衆電話\n";
}
else
{
moji = moji + moji2 + "\n";
}

}
catch (Exception ex)
{
moji = ex.Message;
}

// richTextBox側のスレッドに AddRecievedDataメソッドのポインタを渡して、
// 受信文字列を追加させる
AddRecievedDataDelegate add = new AddRecievedDataDelegate(AddRecievedData);
this.richTextBox1.Invoke(add, moji);
}
結果:
1221112260457771111
12月21日(月)12時26分 0457771111
1221112
startIndex に文字列の長さより大きい値を指定することはできません。
パラメータ名: startIndex260457771111
startIndex に文字列の長さより大きい値を指定することはできません。
パラメータ名: startIndex

Substringを削除すると「startIndex に文字列の長さより大きい値を指定することはできません。」というようなエラーは出てきません。
receivedData = this.serialPort1.ReadExisting();
を文字列を直接代入した場合はエラーは発生しません。

これをどのようにすれば正常に動くのでしょうか。

また、ACKが正常に送信できてないみたいなのも解れば助かります。
よろしくお願いします。

C#でCTI機能の実現を目指しております。
プログラムは以下サイトからDLして改造しています。
http://tmp.junkbox.info/e14.html
しかし、エラーが頻発し原因不明です。

構成、仕様としては、
アロハPC1という機械から電話番号データを受信しPCに受け渡し。
・データを受け取る(ここは問題なし)
データ形式は
STX(02H)、着信日時(月日曜時分9桁)、電話番号(20桁)、ETX(03H)
として送られてきます。
例) 1214112050457771111
・正常データの場合はACK(06H)を返信(これをしない場...続きを読む

Aベストアンサー

>・データを受け取る(ここは問題なし)
確認も無しに断言してはいけません。

このプログラムの問題点は、受信したデータ(receivedDat)が必ずしも31文字にならないことです。
SerialPortのDataReceived()イベントは、1文字受信するたびに発生します。
従って受信したデータには、ReadExisting()した時点でSerialPortに受信されている分しか入りません。
解決方法を2種類示しますが、動作確認はしていません。

◎解決方法1
ReadExisting()する前にBytesToReadをチェックして31文字未満ならReadしない。

◎解決方法2
一度に1文字ずつReadして文字をつないでいく。
このとき、
STXを受信する前は、Readしたデータは捨てる。(受信データは空にする)
STXを受信した後は、Readしたデータを受信データに継ぎ足していく。
ETXを受信したら(継ぎ足したデータがETXなら)、受信データ長を確認してACK送信にすすむ。

QSerialPortの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 でどのように書けばよいのかわかりません。
どなたかご教授ください。
よろしくお願いいたします。

Visial Basic 2005 にて SerialPort コンポーネントを使ったアプリを作っています。
当初、Microsoft のサンプルを参考に

SerialPort1.ReadLine

でデータを受信していたのですが、この方法だとバッファ内から再度同じデータを受信してしまうらしく、新しいバッファからデータを受信しないとイベントが発生する毎に古いデータを読み取ってしまいます。

そこで調べていたところ、Microsoft のフォーラムで以下のような Visual C# のソースを見つけました。

(以下引用)
> if (serialPort1.BytesToRe...続きを読む

Aベストアンサー

こんにちは、もう解決しているかもしれませんが。
ReadLineのヘルプには、
入力バッファ内の NewLine 値まで読み取ります
と記載してあります。Framework2.0からの機能なんですね。

私の場合、データ受信後その内容により返事を返すまでの間
次のデータを受信することは無い場合が多いので
DataReceivedイベントでSerialPort.Readを利用しています。
ReadLineは使用したことが無いのでわかりませんが
Readの場合、読み込んだデータがバッファに残っているということはありません。

QVB2010で、シリアル通信をするには

VB2010で、シリアル通信をするには

シリアルポートをopenしようとすると、エラーで弾かれてしまいます。
どのように対処したら良いですか?

使っているソースコードは、下記の通り。

Private Sub ButtonRsStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRsStart.Click
Try '例外処理のはじまり
If SerialPort1.IsOpen = True Then 'ポートはオープン済み
MessageBox.Show("すでに" & SerialPort1.PortName & "は接続されています。", "エラー",
MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If
SerialPort1.PortName = "COM1" 'オープンするポート名を格納
SerialPort1.Open() 'ポートオープン
PORT_STATE.Text = "OPEN"
Catch ex As Exception '例外処理
MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

End Sub
---------------

エラーが発生する場所は、「Catch 」になります。
エラーメッセージは、「ポート 'COM1' へのアクセスが拒否されました。」です。

何が原因なのか、さっぱり分かりません。
ヒントになりそうな解答を頂けないでしょうか?

VB2010で、シリアル通信をするには

シリアルポートをopenしようとすると、エラーで弾かれてしまいます。
どのように対処したら良いですか?

使っているソースコードは、下記の通り。

Private Sub ButtonRsStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRsStart.Click
Try '例外処理のはじまり
If SerialPort1.IsOpen = True Then 'ポートはオープン済み
MessageBox.Show("すでに" & SerialP...続きを読む

Aベストアンサー

> どのアプリが「COM1」を、使っているのか判る方法は在りますか?

私も知りませんが、デバイスマネージャでモデムのデバイスのプロパティを見て、COM1になっているかどうかですね。

私のマシンではモデムはCOM3になっていますが、設定の変更をすればCOM1にすることもできますので。

あるいはデバイスマネージャで通信関係らしきデバイスのプロパティを調べてみる位しか思いつきません。

ちなみに、私のマシンではデバイスマネージャで「ポート(COMとLPT)」を見ると、COM1もCOM3
も表示されません。
モデムを見るとCOM3になっています。

COM1を指定してプログラムを動かすと「ポート 'COM1' は存在しません。」と表示します。

COM3を指定すると正しくオープンできます。

COM3を他の通信ソフトでオープンしておいて、COM3を指定してプログラムを動かすと「ポート 'COM3' へのアクセスが拒否されました。」と表示します。

この結果から推測すると、xcode_15さんのマシンはCOM1を他のソフトが使用しているということになります。

> どのアプリが「COM1」を、使っているのか判る方法は在りますか?

私も知りませんが、デバイスマネージャでモデムのデバイスのプロパティを見て、COM1になっているかどうかですね。

私のマシンではモデムはCOM3になっていますが、設定の変更をすればCOM1にすることもできますので。

あるいはデバイスマネージャで通信関係らしきデバイスのプロパティを調べてみる位しか思いつきません。

ちなみに、私のマシンではデバイスマネージャで「ポート(COMとLPT)」を見ると、COM1もCOM3
も表示されません。
モデム...続きを読む

QCloseとDisposeの違い

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、タイマーコントロールのイベントに記述していますと、それは実行され続けます。

これを防ぐために、Me.Dispose() を使います。すると、きれいにプロセスは終了し、イベントは発生しない模様です。

そこで、「フォームを閉じる」意味のMe.Close() をすべてMe.Dispose() に変えてしまいました。確実にプロセスを破棄出来ると思ったからです。Webで調べると、違いは「再利用できる、できないの違い」という答えがありましたが、それはきっと、ファイルやオブジェクトのことで、フォームの場合は、再びShowまたはShowDialogで表示させることは可能でしたので、特に問題は感じていませんでした。

ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。Me.Close() に変えるとうまくいきました。

わけわからなくなってきました。。。

ちなみに、その残ったフォームは、スタートアップフォームであり、別のフォームからShowまたはShowDialogメソッドで呼び出したものではありません。

ここで4つの仮説を立ててみました。

1. ShowDialogで呼び出したフォームは、Me.Dispose()、Showで呼び出した、あるいは、スタートアップフォームは、Me.Close() すれば破棄できる

2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

3. 呼び出し方ではなく、別の要因が存在する

4. 併記する必要がある場合がある

Me.Close()
Me.Dispose()

または、

Me.Dispose()
Me.Close()



どれが正しいのでしょうか?どなたがご存じの方がいらっしゃいましたら、ご教授いただけませんでしょうか? どうぞよろしくお願い申し上げます。ありがとうございました。

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、...続きを読む

Aベストアンサー

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。
Me.Close() に変えるとうまくいきました。

通常はどちらでもうまくいきます。

>2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

ShowDialogの場合は、メソッド内部で、ハンドルが破棄されているため、Close()メソッドの際にDispose()メソッドが呼び出されます。

>3. 呼び出し方ではなく、別の要因が存在する

そう思います。

>4. 併記する必要がある場合がある

インスタンスを明示的に破棄したほうがよい場合は多く存在します。
Disposeが使えるメンバはIDisposableをインターフェースとして持っているメンバです。
これらのメンバは、外部とのやり取りを行うものが多くあります。
たとえばSQLClientに含まれるようなメンバです。

外部とのコネクションを確実に破棄を保障してほしいなどという場合がありますよね、このようなときに使用します。

Using構文を使用するのとまったく同じ理由になります。
正確にはUsing構文を使用できるメンバには条件があります、IDisposableをインターフェースとして持っているメンバに限るというものです。

ほかにもガーベージコレクタによるファイナライズを伴うかどうかという違いがあります。
Disposeの場合はファイナライズが同時に行われるため、使用していたメモリ空間を開放することができます。

上記のような理由により、
Me.Close()
Me.Dispose()
は両方書いたほうがよいと思います。

蛇足ですが、
Me.Dispose()
Me.Close()
はエラーになります。
Me.Dispose()により、Me本体(インスタンス)は削除されてしまいます。
存在しないMeに対してCloseメソッドを要求することはできないためです。

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリ...続きを読む

QVB2010 COMポートからのバイナリ受信

オシロスコープからの画像データ(40kバイト程度のtifファイル)をPCのCOMポートから受信し
保存するプログラムを作成しているのですが、受信データを正しくPC上に保存できません。

具体的には下記のコードでtifファイルは作成されますが、容量が数kバイトで明らかに不足
しています。

MsgBoxを有効にして受信バッファサイズや書込み長さを確認しましたが、「OK」ボタンを押す
たびに下記の表示になります。COMポートのバッファサイズが4096バイトなので「dat.Length」
をすべて足し合わせると本来の受信データサイズになると思うのですが、PC上に作成された
ファイル容量から「dat」が常に上書きされているような気がします。

正しく保存するにはどのような修正が必要でしょうか?

【MsgBoxを有効にしたときの表示値(OKを押すたびに数値が変わる)】
「dat.Length」
183
4075
4072
4092
4088
4084
4085
4092
4059
4078
3910






「ByteToRead」
4060
1508
324
908
2334
1785
70
227
400






【作成したコード】
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As_ System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived


' シリアルポートからデータ受信
Dim dat As Byte() = New Byte(SerialPort1.BytesToRead - 1) {}
SerialPort1.Read(dat, 0, dat.GetLength(0))

'MessageBox.Show(dat.Length)
'MessageBox.Show(SerialPort1.BytesToRead)

File.WriteAllBytes("C:\test1.tif", dat)

SerialPort1.DiscardInBuffer()


End Sub


【環境】
OS:Win7
VB:2010
ポート設定:SerialPortクラス標準からポート番号以外は変更なし

オシロスコープからの画像データ(40kバイト程度のtifファイル)をPCのCOMポートから受信し
保存するプログラムを作成しているのですが、受信データを正しくPC上に保存できません。

具体的には下記のコードでtifファイルは作成されますが、容量が数kバイトで明らかに不足
しています。

MsgBoxを有効にして受信バッファサイズや書込み長さを確認しましたが、「OK」ボタンを押す
たびに下記の表示になります。COMポートのバッファサイズが4096バイトなので「dat.Length」
をすべて足し合わせると本来の受...続きを読む

Aベストアンサー

>PC上に作成された
>ファイル容量から「dat」が常に上書きされているような気がします。

http://msdn.microsoft.com/ja-jp/library/system.io.file.writeallbytes%28v=vs.100%29.aspx

「新しいファイルを作成し、指定したバイト配列をそのファイルに書き込んだ後、ファイルを閉じます。 既存のターゲット ファイルは上書きされます。」
と書かれているのですから、当然かと。

OpenWrite()辺りで開いて、ファイルの末尾にシーク、書き出し。
となるかと。
# 「VB バイナリファイル 書き込み」辺りで検索すれば見つかるんじゃないですかね?
# http://msdn.microsoft.com/ja-jp/library/szz5syt3%28v=vs.100%29.aspx とか。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報