投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/9/21 15:22:24
> このように実際の時間の何倍もかかってしまっていますが、

どういうコードによってその結果が齎されているのかが分かりませんでした。


ひとまず、タイマーを何のために用いているのかにもよりますが、そもそも
「受信処理」のスレッドは、画面系(UI)のスレッドとは分離されていますよね。

また、タイマーにもいろいろあるわけで…。
http://www.atmarkit.co.jp/ait/articles/0511/11/news117.html
http://www.atmarkit.co.jp/ait/articles/0511/11/news118.html
http://www.atmarkit.co.jp/fdotnet/dotnettips/374timerstimer/timerstimer.html



> これはシステム(PCの性能やその時の稼働状況)に依存するものでしょうか。

データの受信タイミングと、グラフの描画タイミングはそもそも無関係です。
データを 1 件受け取って、直ちに描画を始めるのではなく、

(a) 受信処理:シリアル通信で送られてきたデータをフィールド変数に蓄えていく
(b) 加工処理:受信データをグラフ用の座標データに切り出す
(c) 描画処理:座標データを Chart にプロットしていく

という 3 つの独立した作業が存在するという前提で考えてみては如何でしょう。


(a) は DataReceived イベントのことで、データ受信のたびに呼び出されるものです。
ここでは、グラフへのプロットなどの「時間のかかる処理」を行わないようにします。
(Invoke メソッドの呼び出しも極力避けます)


(c) は .Points.AddXY などを呼び出すための処理で、a とは別のスレッドで動作します。


(b) の加工作業は、さらに別の作業スレッドで行わせることもできなくはないですが、
時間を要するものでないなら、a もしくは c のいずれかの作業時に一緒に行えば十分でしょう。



データは逐次送られてくるはずなので、a の処理は「複数のデータを蓄えられるようにしておく」か、
もしくは「直近のデータのみを保持し、以前のデータは読み捨てるようにする」必要があります。

ただし、a と c はスレッドが異なりますので、呼び出されるタイミングは必ずしも一致しません。

たとえば、a の処理が 7 回発生したけれど、c は 1 回しか呼ばなかった場合、
「溜めておいた 7 件のデータをまとめて追加プロット」させるようにするか、もしくは
「未処理の 6 回分は読み捨てて、7 回目の直近データのみを追加プロット」させます。

逆に、a の受信処理が発生しないタイミングで c が呼ばれるようなことがあれば、
c は「グラフを一切操作することなく Return する」ということになるでしょう。


c をどのタイミングで呼び出されるようにするか、という点に関してはいろいろな考え方があります。
たとえば、「データ更新」ボタンを押したときだけグラフを再描画しなおすようにしてもよいですし、
a が発生するたびに BeginInvoke すると言う手もあります。あるいはタイマーを通じて、
一定間隔で「新しいデータが来ていた時だけ追記する」形にすることもできます。あるいは
Application クラスの Idle イベントで、追記データの有無を確認するとか。


また、受信するデータ量が非常に多いような場合には、
受信したデータすべてをプロットするのか、適宜間引くのかも検討せねばなりません。
(間引く場合は、b または c の段階で処分します)