1
1
テーマ、知りたいこと
装置制御PLCとの通信にソケット通信を使っています。
送受信する都度connectとshutdownをしています。
頻度としては200msec毎に4〜5回のconnectとshutdownを繰り返しています。
connectとshutdownは頻繁に行わない方が良いのでしょうか?
背景、状況
PLCとの通信プログラムをメインプログラムから分離してdllにする際1ビットの値を取得する関数内でconnectとshutdownを行うように作ってしまい、そのためメインプログラムから1ビットの値を取得する都度connectとshutdownをしてしまうプログラムになっています。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答34件
#1
総合スコア85458
投稿2024/07/26 10:38
connectとshutdownは頻繁に行わない方が良いのでしょうか?
別にかまいません。
connectしっぱなしのほうが、処理が減るので、CPUやハブの消費電力が減る(温度に影響)とか、
その分処理が速くなるかもというメリットはありますが、
(実際に速くなるかどうかは全体の処理内容次第。間にあるネット機器の数が多いほど効く)
そこまで気にしないなら、プログラムロジックが簡単な方がメンテしやすいしバグも出にくいです。
処理速度を少しでも速くしたいという要件があり、コネクト処理のオーバヘッドの影響が大きいと判断したのなら、
繋ぎっぱなしにするようなプログラム修正に取り組むのでしょうね。
#2
![退会済みユーザー](https://ddjkaamml8q8x.cloudfront.net/profileImages/deletedUser/icnUserSample.jpeg)
退会済みユーザー
総合スコア0
投稿2024/07/26 10:51
そもそも前提があまりにもあやふやなので、意見を書きたくなかったのですが、書いちゃった人がいるので一応懸念点を書いておきます。connectとshutdownは頻繁に行わない方が良いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#14
![退会済みユーザー](https://ddjkaamml8q8x.cloudfront.net/profileImages/deletedUser/icnUserSample.jpeg)
退会済みユーザー
総合スコア0
投稿2024/07/27 02:51
編集2024/07/27 03:10どれだけ離れているのか知りませんが、到達保証や順序保証のないUDPを、TCPすらまともに使えてなさそうな人に使わせるのは不安しかない気もしますね
いいねとかしないでもらえますか?どれだけ離れているのかを含む、どちらが適しているのかを含む全ての判断材料を持ってるのはあなただけですよ
もし順序保証があり、ロスがありえないなら、UDPの方が適しているのは明らかです
そしてより良い選択・判断をする責任を持つのはあなたです
仕事なので
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#16
総合スコア85458
投稿2024/07/29 12:01
今起こっている問題は「夜通し動かし続けると翌朝落ちて画面が消えていることがある。タスクマネージャーで見ても消えている。ログを見ても何が起こったのかよくわからない。」という問題です。
なんと。障害が起こっていたのですね。
ポート枯渇していればconnectが失敗すると思うので、例外を握りつぶしていない限りは、その例外が起こったというメッセージががログに出そうですけど、そもそもログを書いてないとかですかね?あるいは例外を握りつぶしている?
それはそれとして、ポート枯渇が起こっているかどうかは、一定時間毎に、
echo $(date "+%F %T") $(netstat|grep "^tcp"|wc -l) >> どこかのファイル
とか実行してTCPの使用ポート数の変化を見れば見当つきそうです。
connectを起動時のみにしたら動かなくなったのでやめました。
「プログラムをちゃんと書き換えることに掛かる負荷」に対して「翌朝落ちてて画面が消えている事による困り具合」が無視できる程度なら、それでも良いと思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#22
#19
やりたいことは↓こんな感じです。
C#
1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading; 9using System.Threading.Tasks; 10using System.Windows.Forms; 11using Timer = System.Threading.Timer; 12 13namespace WindowsFormsApp2 14{ 15 public partial class Form1 : Form 16 { 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 private static object lockObject = new object(); 23 private static int Counter = 0; 24 public delegate void DelegateUpdateText(); 25 private static Timer timer; 26 27 private void Form1_Load(object sender, EventArgs e) 28 { 29 timer = new Timer(TimerCallback); 30 timer.Change(0, 200); 31 } 32 33 private void button1_Click(object sender, EventArgs e) 34 { 35 lock (lockObject) 36 { 37 MessageBox.Show("待機中");// ソケット通信のデータ送信の代わり 38 } 39 } 40 void TimerCallback(object state) 41 { 42 updateText(); 43 } 44 45 private void updateText() 46 { 47 this.Invoke(new DelegateUpdateText(this.OnUpdateText)); 48 } 49 private void OnUpdateText() 50 { 51 lock (lockObject) 52 { 53 Counter++; 54 label1.Text = Counter.ToString();// ソケット通信の受信の代わり 55 } 56 } 57 } 58}
待機中はカウントアップが止まってほしいのに止まってくれません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#23
総合スコア10383
投稿2024/08/02 12:27
lockステートメントは複数のスレッドでの排他処理に使用するもので同一スレッドでlockしてもロックされません。
提示されたコードですと、MessageBoxを表示しているスレッドとOnUpdateTextはOnUpdateTextがInvokeで呼び出されているために同一のスレッドとなっていてlockがかかりません。
C#
1 private void updateText() 2 { 3 lock (lockObject) 4 { 5 this.Invoke(new DelegateUpdateText(this.OnUpdateText)); 6 } 7 } 8 private void OnUpdateText() 9 { 10 Counter++; 11 label1.Text = Counter.ToString();// ソケット通信の受信の代わり 12 }
といった感じでInvokeする前にlockすれば思った動作になるかと思います。
ただ現在のやりとりが意見交換の主題から外れているので新たに質問すべきだと思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#30
総合スコア11893
投稿2024/08/05 08:19
(横から便乗質問の形になり恐縮ですが)
#23 のコードに対する疑問なのですが……
lock
中にスレッド切り替えるような処理って危なそうに見えるのですが,どうなのでしょう?
(UI ではないスレッドで実施されていると思われる)updateText()
内での lock
の直後に
UI スレッド側が lock
に達して待ち状態に入った場合,
その状態での Invoke
って可能なのでしょうか?
(ここでデッドロックする?)
lock
中には排他すべき処理(通信処理)だけを行うようにして,
その他のこと(何かしら UI スレッドで実施せねばならないと思われる作業)については
lock
解除後に Invoke
(とか BeginInvoke
?)するのが 良い?/安心?/etc な可能性はないのでしょうか?
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#31
総合スコア10383
投稿2024/08/05 10:41
ご指摘の通り動作しなくなると思います。
私もlockステートメントの本来の使い方としては異なるスレッド(UIスレッドではないスレッド)間にて排他処理を行うといったものでありそのlock中の処理でスレッドを変更するという使い方をすべきではないと思っています。
しかし今回は、目的の動作が何故できないのかといった説明の為にサンプルを簡単に変更するとしたらということで
変更を提示しました。
デッドロックしてしまう注意点を提示できなかったのはこちらの落ち度となります。
申し訳ありませんでした。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#32
家に帰ってこんな感じのコードを書いてみたらなんとなく期待通りに?動いています。
C#
1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading; 9using System.Threading.Tasks; 10using System.Windows.Forms; 11using Timer = System.Threading.Timer; 12 13namespace WindowsFormsApp2 14{ 15 public partial class Form1 : Form 16 { 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 private static object lockObject = new object(); 23 private static int Counter = 0; 24 private static int Counter2 = 0; 25 public delegate void DelegateUpdateText(); 26 private static Timer timer; 27 private static Timer timer2; 28 29 private void Form1_Load(object sender, EventArgs e) 30 { 31 timer = new Timer(TimerCallback); 32 timer.Change(0, 200); 33 } 34 35 private void button1_Click(object sender, EventArgs e) 36 { 37 timer2 = new Timer(TimerCallback2); 38 timer2.Change(0, 200); 39 } 40 void TimerCallback(object state) 41 { 42 timer.Change(0xFFFFFFFF, 0xFFFFFFFF); 43 UpdateText(); 44 timer.Change(200, 200); 45 } 46 47 private void UpdateText() 48 { 49 lock (lockObject) 50 { 51 this.Invoke(new DelegateUpdateText(this.OnUpdateText)); 52 } 53 } 54 private void OnUpdateText() 55 { 56 Counter++; 57 label1.Text = Counter.ToString();// ソケット通信の受信の代わり 58 } 59 60 void TimerCallback2(object state) 61 { 62 timer2.Change(0xFFFFFFFF, 0xFFFFFFFF); 63 UpdateText2(); 64 timer2.Change(200, 200); 65 } 66 67 private void UpdateText2() 68 { 69 lock (lockObject) 70 { 71 this.Invoke(new DelegateUpdateText(this.OnUpdateText2)); 72 } 73 } 74 private void OnUpdateText2() 75 { 76 Counter2++; 77 label2.Text = Counter2.ToString();// ソケット通信の送信の代わり 78 } 79 } 80}
なんか間違っているでしょうか?
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#34
https://ez-net.jp/article/FB/beofK19H/z5CwHgjxeJRA/
↑こちらを参考に短くしてみました。
大型連休中に止まらなければ良いのですが、、、
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。