RS232Cと TCP/IP の送受信の排他制御 VB.net
RS232Cで通信しているのですが、送信時に1~30秒ほどの待ちが発生することがあり、
その解消に苦労したので記録します。
○ SerialPortクラスは使わずに、WindowsAPI WriteFile(), ReadFile()を使用している。
(ReadFileは別スレッドでループを回している)
○ 開発環境のハイスペックPCでは待ちが発生しない。
○ RS232Cポートを増設して、そちらで試しても待ちが発生する。
○ USB-RS232C変換ケーブルを使用しても待ちが発生する。
○ フリーのRS232Cテストツールを使用したところ、待ちは発生しない。
○ ケーブルや、通信相手を変更しても、待ちは発生する。
○シリアルポートの設定、BIOSの設定、レジストリの割り込み設定、
デバイスマネージャのIRQ設定を調整しても、待ちが発生する。
過去に作ったプログラムなのですが、
当時はSerialPortクラスでの読み取りに何らかのトリガーが必要だと思い込み、
試しもせずにWindowsAPIを使うという、イバラの道(初心者には)を選んだのでした。
その時は書き込み時の遅延はあまり問題にならなかったのですが、
今回通信部分を流用して別のプログラムを作成したところ、
今回の送信時の遅延が発覚しました。
ネットでダウンロードしたツールだと待ちが発生しないので、
明らかに私のプログラムに問題があります。
正常に動くツールはSerialPortクラスを使っているということで、
SerialPortクラスの使い方を眺めていると、
普通に受信時にイベントがはっせいするだけでしたので、
急遽、送信部分と受信部分をSerialPortクラスを使うように修正しました。
あっさりと送信時の遅延は解消ました。
色々試していくうちに、
読み取りのループを止めると書き込み時の遅延が発生しないことがわかりました。
ということは、送信と受信の競合が問題になりそうですね。
ということで、WriteFile() ReadFile() しているところに、
SyncLock _syncObj という感じで、排他制御を入れたところ、
送信時の待ちは解消されました。
RS232C通信の送信と受信は排他すること。(もしくはSerialPortクラスを使用する)
今度はTCP/IPの通信なのですが、送信と受信をSyncLock _syncObjしたところ、
スペックの低いPCだとなぜかデッドロックが起こる、
ということが以前にありました。
こちらはSocketクラスを使用しています。
昔のコードを掘り返して確認すると、
送信部の SyncLock _syncObj をやめることで、
デッドロックを解消していました。
AIとお話ししたところ、
送信部分のSocket.Send() と受信部分のCallBackがロックを取り合っていることが原因で、
TCP/IP 通信では Socket.Send() した後に、
受信の待ちが発生することがあるので、送信と受信でロックを取り合ってはダメとのことでした。
TCP/IP(Socket)通信では、送信と受信は排他しないこと。
※送信、受信が重複しないように、別のロックで、送信、受信を別々にロックした方が良い。
ということでした。
ネットワーク名が見つかりません ファイルサーバの不具合
Windows11への乗り換えを進めていますが、インストール後に必要なファイルを、
ファイルサーバからダウンロードしようとしたところ、
「ネットワーク名が見つかりません」のような(正確な文言は忘れました)エラーが出て、
ダウンロードができません。
???
別のPCでファイルサーバを見ると普通にアクセスできますが・・・。
もう一度別のPCを起動して、ファイルサーバへのアクセスをチェックすると、
同様に「ネットワーク名がみつかりません」と出ました。
これはファイルサーバのエラーのようなので、とりあえず再起動しました。
なぜか再起動に時間がかかりましたが、無事に起動し(冷や汗をかきました)、
アクセスチェックすると、アクセス可能になりましたが、
容量が少なくなってきているのが気になったので、
とりあえずUSBハードディスクを付けて、そこにファイルを逃がすことにしました。
フォーマットしてマウント、fstabにも記述を追加し、起動時に自動マウントするようにします。
ちなみに、
UUID=xxxxxxxx /mnt/usbhd3 ntfs nofail 0 0
のように記述しましたが、
nofailを指定しておかないと、usbハードディスクを外すとOSが起動しなくなるので注意してい下さい。
そして、容量をくっているディレクトリを丸ごとコピーしましたが、
間違ってマウントしていない /mnt/usbhd にコピーしてしまい、
一瞬で/mntの容量があふれてしまいました。
以前に同じようなことがあって、inodeが枯渇したので、 df -iでチェックすると、やはり99%とかになっています。
すぐに /mnt/usbhdのファイルをすべて削除して、もう一度 df -i しても 90% までしか減りません。
??????
df -h すると /dev/mapper/cl-root が100%使用されている・・・。
根本的な容量不足でした。
Sambaのログファイルが大量に出力されていて、そのせいのようです。
full_audit から read pread write pwrite を削除したところ、ログが大幅に減ったのでこれで大丈夫。
運よくディスク容量不足を発見することができて、ラッキーでした。
Sambaがおかしい場合は、容量不足を疑ってみましょう。
.netframework 起動が異常に遅い。
.netframework4 client profile で昔に作成したソフトの改修依頼が入った。
修正後、起動テストすると、起動までに30ほどかかる。
初回だけではなく、二度目でも三度目でも同じ。
???
改修前のソフトの起動は1秒以内。
なぜ・・・・。
VisualStudioが新しくなっているせいかと考え、古いVisualStudioでビルドし直してみるが変わらない。
OSがWindows7とはいえ、改修前はすぐに起動しているのに・・・。
何かが記憶を通り過ぎた。
これは前にもあった。
そうだ。
ディジタル署名が検証できないのだ。
ビルド後にディジタル署名していたが、こいつを検証するサーバは別セグメントにあり、アクセスできない。
Windows7が残っているこのLANは閉鎖環境なのだ。
ディジタル署名は、署名されていれば当然検証が必要となり、サーバにアクセスできないためタイムアウトを待つということか。
以前にも同じようなことがあって、調べた気がする。
ディジタル署名を外したら治りました。
閉鎖環境でディジタル署名するなかれ。
NTPサーバに同期できない chrony Windows11 plala
Windows11をインストール後、NTPサーバを設定して同期しようとすると、
「ピアに到達できません」
とのエラー。???昨日ルータをいじったせいかも?
色々試すと、Linuxサーバのchronyがダメらしい。RTX810には同期できます。
どうも上位のNTPサーバとchronyが同期できないと、クライアントPCも同期できないようなので、
上位のplalaのNTPサーバに直接同期してみると、、、、やはり失敗しました。
上位をplalaをやめてnict とsakura にして、chronyを再起動すると・・・治りました!
・・・・「ぷららのNTPサーバーは、2022年3月31日をもって終了しました。」
知りませんでした。
ILMergeで失敗する ~2
またILMergeがうまくいきません。
だいたい、プロジェクトが締め切り間近になって、ほぼ開発が終了したころに、
やってくるこの時間です。
プロジェクトをリビルドすると、依存関係がうまくいっていないのか、ビルドに失敗します。
カスタムコントロールのプロジェクトが先にビルドされれば大丈夫と思い、依存関係をいじったら
ビルドできなくなりました。
色々と恐る恐る、いじってみると、
「アセンブリに署名」が問題をおこしているようでした。
カスタムコントロール等の「アセンブリに署名する」のチェックをすべて外し、ビルドしなおすと段々参照が治っていきました。
最悪の状態ではSystem の参照さへみつからなくなっていたのでしたが・・・。
色々な参照を削除して、もう一度追加したりしているうちに、なんとかビルドできるようになりました。
さて、次は「アセンブリに署名」できるようにします。
これは経験があるのですが、私の環境ではオレオレ証明書を使用しているせいか、Fodyで単一実行ファイルを作ると、この現象が起きます。
Nugetパッケージマネージャーを確認すると、やはりFodyがインストールされてました。
Custra.Fody、Fodyの順にアンインストール(怒られたので)。
すると、「アセンブリに署名」でビルドできるようになりました。
最後に、いつものILMergeです。
前回、手動でマージするとエラーが表示されることにようやく気付いたので、それで行きました。
まずはやはりプロジェクトに変な文字を使用しているせいか、パスがおかしくなっていました。
それだけでは解決しません。
「
An exception occurred during merging:
Unresolved assembly reference not allowed: System.Diagnostics.Tracing.
場所 System.Compiler.Ir2md.GetAssemblyRefIndex(AssemblyNode assembly)
場所 System.Compiler.Ir2md.GetTypeRefIndex(TypeNode type)
場所 System.Compiler.Ir2md.VisitReferencedType(TypeNode type)
場所 System.Compiler.Ir2md.GetMemberRefIndex(Member m)
場所 System.Compiler.Ir2md.GetMethodToken(Method m)
場所 System.Compiler.Ir2md.VisitMethodCall(MethodCall c ・・・・・ 」
と表示されます。Unresolved assembly reference not allowed かー。
参照が解決できないとなっていたので、バージョンを変えて試してみます。
開発している.NetFrameworkは、4.8 ですが、ILMergeで指定しているのは、4.6.2だったので、そこを4.8に・・・してもダメでしたが、
4.7.2にすると大丈夫でした。でも・・・今試したら4.8でも通りました。。。。よくわからないが、何とかなりましたね・・・。
もう少しきちんと勉強しようと思います。
※ 今以前の記事を見たら、今回とほぼ同じことが書いてある!!!うー。。。
ILMerge で失敗する Duplicate type
さて、またもMergeできません。
もうわからないので、以前のPCで(比較的ILMergeがうまくいっていた)
Releaseフォルダをそのままコピーして、手動でILMerge(VisualStudioのプロンプトを使用)したところ、
エラーメッセージが出ました。
An exception occurred during merging:
ILMerge.Merge: ERROR!!: Duplicate type 'System.Runtime.CompilerServices.AsyncMethodBuilderAttribute' found in assembly 'System.Threading.Tasks.Extensions'. Do you want to use the /alllowDup option?
場所 ILMerging.ILMerge.MergeInAssembly(AssemblyNode a, Boolean makeNonPublic, Boolean targetAssemblyIsComVisible)
場所 ILMerging.ILMerge.Merge()
場所 ILMerging.ILMerge.Main(String[] args)
ということで、AllowDupオプションを付けてマージします。
C:\Windows\System32>"C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe" /allowDup /internalize /ndebug /targetplatform:"v4,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2" /wildcards /out:"C:\Relase\Merge\test.exe" "C:\Relase\test.exe" "C:\Relase\*.dll"
やっとマージできました!