DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Delegateについて

  • 題名: Delegateについて
  • 著者: HideKung
  • 日時: 2009/11/09 8:57:15
  • ID: 25743
  • この記事の返信元:
    • (なし)
  • この記事への返信:
  • ツリーを表示
環境/言語:[WinXP&Vista VB2008]
分類:[.NET]

お世話になります。Delegateについてご教示をお願いします。
以下のようなプログラムでシリアル通信データを取り込んでいるのですが、一日に数回ほどプログラムが固まります。
そもそもDelegateのしくみが良くわかっておりませんので、原因と対策についてご教示をお願いします。
Delegate Sub AddDataDelegate(ByVal str As String)
Private Sub AddData(ByVal str As String)
Dim str1 As String : Dim sta As String()
Try
str1 = str
sta = str1.Split(","c)
If String.Compare(sta(0), "$GPGGA") = 0 Then ' 緯度、経度
xm = Double.Parse(sta(4))
ym = Double.Parse(sta(2))
xm = CInt(xm / 100 - 0.5) * 3600 + (xm - CInt(xm / 100 - 0.5) * 100) * 60
ym = CInt(ym / 100 - 0.5) * 3600 + (ym - CInt(ym / 100 - 0.5) * 100) * 60
End If
If String.Compare(sta(0), "$GPHDG") = 0 Then ' 方位
dir = Double.Parse(sta(1))
End If
If String.Compare(sta(0), "$GPDBT") = 0 Then ' 深度
dep = Double.Parse(sta(3))
End If
If String.Compare(sta(0), "$GPVTG") = 0 Then ' 対地速度(ノット)
knot = Double.Parse(sta(5))
End If

Catch ex As Exception
str = ex.Message
'SerialPort1.Close()
'SerialPort1.Open()
End Try

End Sub

Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim strDataReceived As String
Dim add As New AddDataDelegate(AddressOf AddData)
Try
strDataReceived = SerialPort1.ReadLine
Catch ex As Exception
strDataReceived = ex.Message
End Try
PictureBox1.Invoke(add, strDataReceived)
End Sub
■No25743に返信(HideKungさんの記事)
> 以下のようなプログラムでシリアル通信データを取り込んでいるのですが、一日に数回ほどプログラムが固まります。

  突っ込みどころが多くて・・・

  推測ですが、AddDataDelegate()内にコードが無いのですが、恐らく
  得られたデータで描画処理を行っていると思います。

  一般的にデリゲート処理や描画処理は、よりコストの大きい処理と
  なり、もしかしたらAddDataDelegate処理中に次データの受信が発生
  して、再入してませんか?

  ボーレートやPCの性能によっては、ありえますので・・・

  それと、DataReceivedイベントが発生しても、
  If e.EventType = SerialData.Chars Then
  として、イベントの種類をちゃんと判定して処理して下さい。

  あとできれば、受信の取りこぼしの可能性を考慮し、タイムアウト
  処理を追加したりすればよりよいかと・・・

以上。
■No25744に返信(オショウさんの記事)
早速のご回答ありがとうございます。
システム概要を先に記述すべきでした。お詫びいたします。

>   推測ですが、AddDataDelegate()内にコードが無いのですが、恐らく
>   得られたデータで描画処理を行っていると思います。

描画処理は1秒間隔のタイマーで行っており、シリアル通信とは独立させています。
通常、描画処理は0.1秒程度で終わります。
ちなみに、シリアル通信では、100バイト程度の文字列が1秒に一回受信されます。
ボーレートは4800です。
このような状況の中で、AddDataDelegate()内にはどのような処理を入れるべきでしょうか?

>   それと、DataReceivedイベントが発生しても、
>   If e.EventType = SerialData.Chars Then
>   として、イベントの種類をちゃんと判定して処理して下さい。

ご教示の処理を追加してみます。

>   あとできれば、受信の取りこぼしの可能性を考慮し、タイムアウト
>   処理を追加したりすればよりよいかと・・・

はい、それもありかと考えております。
例えばどのような処理になるかヒントをご教示頂ければ幸いです。
  • 題名: Re[3]: Delegateについて
  • 著者: オショウ
  • 日時: 2009/11/09 12:58:34
  • ID: 25747
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No25746に返信(HideKungさんの記事)
> 描画処理は1秒間隔のタイマーで行っており、シリアル通信とは独立させています。
> 通常、描画処理は0.1秒程度で終わります。

  受信したデータをどこかにキューイングして、タイマー処理で読み出して
  描画処理していると?

  じゃ〜そのキューイング部分のアルゴリズムに問題は無いのでしょうか?
  デッドロックしてしまうような・・・

> ちなみに、シリアル通信では、100バイト程度の文字列が1秒に一回受信されます。
> ボーレートは4800です。
> このような状況の中で、AddDataDelegate()内にはどのような処理を入れるべきでしょうか?

  デリゲートする意味が、上記のことよりサッパリ解りません・・・

  受信イベント側では、キューイング処理してやるだけでよいし、
  描画処理はタイマーでキックされ、キューイングバッファにデータ
  があれば、読み出して描画させるだけ・・・

  強いて言うならば、ReadWriteLock使ってキューへの排他制御を入れ
  てやればデッドロックしてしまう可能性は無いかと。

> 例えばどのような処理になるかヒントをご教示頂ければ幸いです。

  え?・・・
  SerialPortの設定でタイムアウト値を設定する項目ありますヨ。

  私はたまたまですが、タイマーを別途作って、コマンド送信後、
  タイマー起動し、受信が先に終わるかタイマーイベントが来るか
  でタイムアウトを判断してます。

  ややこしいかと思いますが、高速で多重な処理を行うような場合
  は、逆に自由度が高くなるので、そうやってます。

※ FAのソフト屋なんで、24時間365日の生産ラインで、機器との
  通信に延々シリアル通信させてますが、そんなトラブルはありま
  せん。経年劣化した関係でシリアルポートが壊れるか、PCが先
  に壊れるか・・・みたいなことになってます。

  多分、アルゴリズム(プログラム)次第でしょう〜

  頑張って下さい。

以上。
>
■No25746に返信(HideKungさんの記事)
> 描画処理は1秒間隔のタイマーで行っており、シリアル通信とは独立させています。
> 通常、描画処理は0.1秒程度で終わります。

  受信したデータをどこかにキューイングして、タイマー処理で読み出して
  描画処理していると?

  じゃ〜そのキューイング部分のアルゴリズムに問題は無いのでしょうか?
  デッドロックしてしまうような・・・

> ちなみに、シリアル通信では、100バイト程度の文字列が1秒に一回受信されます。
> ボーレートは4800です。
> このような状況の中で、AddDataDelegate()内にはどのような処理を入れるべきでしょうか?

  デリゲートする意味が、上記のことよりサッパリ解りません・・・

  受信イベント側では、キューイング処理してやるだけでよいし、
  描画処理はタイマーでキックされ、キューイングバッファにデータ
  があれば、読み出して描画させるだけ・・・

  強いて言うならば、ReadWriteLock使ってキューへの排他制御を入れ
  てやればデッドロックしてしまう可能性は無いかと。

> 例えばどのような処理になるかヒントをご教示頂ければ幸いです。

  え?・・・
  SerialPortの設定でタイムアウト値を設定する項目ありますヨ。

  私はたまたまですが、タイマーを別途作って、コマンド送信後、
  タイマー起動し、受信が先に終わるかタイマーイベントが来るか
  でタイムアウトを判断してます。

  ややこしいかと思いますが、高速で多重な処理を行うような場合
  は、逆に自由度が高くなるので、そうやってます。

※ FAのソフト屋なんで、24時間365日の生産ラインで、機器との
  通信に延々シリアル通信させてますが、そんなトラブルはありま
  せん。経年劣化した関係でシリアルポートが壊れるか、PCが先
  に壊れるか・・・みたいなことになってます。

  多分、アルゴリズム(プログラム)次第でしょう〜

  頑張って下さい。

以上。
  • 題名: Re[4]: Delegateについて
  • 著者: HideKung
  • 日時: 2009/11/10 14:44:01
  • ID: 25757
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No25748に返信(オショウさんの記事)
>   SerialPortの設定でタイムアウト値を設定する項目ありますヨ。

少し思い当たるフシもありますので、さらに実験を進めてみます。
いろいろ情報を頂きありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板