ソケットからデータを読み取り、データから情報 (2 つの整数) を抽出し、抽出した情報をシリアル ポートから送信する小さなアプリケーションを作成しようとしています。
アイデアは、それを開始し、そのまま続行する必要があるということです。要するに、それは機能しますが、長くは機能しません。一貫して短い期間の後、IOExceptions を受け取り始め、ソケットの受信バッファーがいっぱいになります。
スレッド フレームワークは、MSDN のシリアル ポートの例から取られています。
send() の遅延、readThread.Join() は、read() を遅延させて、シリアル ポートの割り込み処理を発生させるための努力ですが、結合機能を誤解していると思います。プロセスをより効果的に同期するか、ソケットからデータが入ってくるときにデータを破棄する必要があります。これで問題ありません。整数データはパンチルト ユニットを制御しており、1 秒間に 4 回でも問題ないと思いますが、どのように達成するのが最善かはわかりません。どんなアイデアでも大歓迎です。
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static bool _continue;
static SerialPort _serialPort;
static Thread readThread;
static Thread sendThread;
static String sendString;
static Socket s;
static int byteCount;
static Byte[] bytesReceived;
// synchronise send and receive threads
static bool dataReceived;
const int FIONREAD = 0x4004667F;
static void Main(string[] args)
{
dataReceived = false;
readThread = new Thread(Read);
sendThread = new Thread(Send);
bytesReceived = new Byte[16384];
// Create a new SerialPort object with default settings.
_serialPort = new SerialPort("COM4", 38400, Parity.None, 8, StopBits.One);
// Set the read/write timeouts
_serialPort.WriteTimeout = 500;
_serialPort.Open();
string moveMode = "CV ";
_serialPort.WriteLine(moveMode);
s = null;
IPHostEntry hostEntry = Dns.GetHostEntry("localhost");
foreach (IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, 10001);
Socket tempSocket =
new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tempSocket.Connect(ipe);
if (tempSocket.Connected)
{
s = tempSocket;
s.ReceiveBufferSize = 16384;
break;
}
else
{
continue;
}
}
readThread.Start();
sendThread.Start();
while (_continue)
{
Thread.Sleep(10);
;// Console.WriteLine("main...");
}
readThread.Join();
_serialPort.Close();
s.Close();
}
public static void Read()
{
while (_continue)
{
try
{
//Console.WriteLine("Read");
if (!dataReceived)
{
byte[] outValue = BitConverter.GetBytes(0);
// Check how many bytes have been received.
s.IOControl(FIONREAD, null, outValue);
uint bytesAvailable = BitConverter.ToUInt32(outValue, 0);
if (bytesAvailable > 0)
{
Console.WriteLine("Read thread..." + bytesAvailable);
byteCount = s.Receive(bytesReceived);
string str = Encoding.ASCII.GetString(bytesReceived);
//str = Encoding::UTF8->GetString( bytesReceived );
string[] split = str.Split(new Char[] { '\t', '\r', '\n' });
string filteredX = (split.GetValue(7)).ToString();
string filteredY = (split.GetValue(8)).ToString();
string[] AzSplit = filteredX.Split(new Char[] { '.' });
filteredX = (AzSplit.GetValue(0)).ToString();
string[] ElSplit = filteredY.Split(new Char[] { '.' });
filteredY = (ElSplit.GetValue(0)).ToString();
// scale values
int x = (int)(Convert.ToInt32(filteredX) * 1.9);
string scaledAz = x.ToString();
int y = (int)(Convert.ToInt32(filteredY) * 1.9);
string scaledEl = y.ToString();
String moveAz = "PS" + scaledAz + " ";
String moveEl = "TS" + scaledEl + " ";
sendString = moveAz + moveEl;
dataReceived = true;
}
}
}
catch (TimeoutException) {Console.WriteLine("timeout exception");}
catch (NullReferenceException) {Console.WriteLine("Read NULL reference exception");}
}
}
public static void Send()
{
while (_continue)
{
try
{
if (dataReceived)
{
// sleep Read() thread to allow serial port interrupt processing
readThread.Join(100);
// send command to PTU
dataReceived = false;
Console.WriteLine(sendString);
_serialPort.WriteLine(sendString);
}
}
catch (TimeoutException) { Console.WriteLine("Timeout exception"); }
catch (IOException) { Console.WriteLine("IOException exception"); }
catch (NullReferenceException) { Console.WriteLine("Send NULL reference exception"); }
}
}
}
}
アップデート:
返信ありがとうございます。
私がやろうとしているのは、データのソケットをポーリングすることです。それが処理されてシリアルポートに送信される場合は、ソケットをポーリングし続け、このプロセス全体をうんざりさせて繰り返します。
私の最初の試みは単一のスレッドを使用しましたが、同じ問題が発生していました。そのため、次のループでさらにデータを送信する前に、シリアルポートにデータを送信できるようにするために、もう少し時間を与える必要があると思いました。シリアルポートにデータを送信しましたが、ソケットを非常に激しくポーリングしています。約 30 秒の操作の後に IOExceptions が発生すると言いましたが、おそらく私が言っているのは、IOExceptions をすぐに見る必要があるということでしょうか?
join 関数の私の解釈は間違っていると思います。理想的には、send() から readThread.Join を呼び出すと、COM ポートをポンピングしながら read() をスリープさせることができますが、send() をスリープ状態にしているようです。 、私は呼び出し関数だと思いますか?? 望ましい結果が得られません。
任意の提案をいただければ幸いです。乾杯。