private void Form3_Load(object sender, EventArgs e)
{
/*usart引數設定*/
serialPort.BaudRate = 115200; //設定波特率
serialPort.Parity = System.IO.Ports.Parity.None; //無奇偶校驗
serialPort.DataBits = 8; //設定資料位數
serialPort.StopBits = System.IO.Ports.StopBits.One; //一個停止位
//定義資料接收事件,當串口收到資料后觸發事件
serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
}
private void usart_connet_Click(object sender, EventArgs e)
{
if (usart_connet.Text == "打開串口") //如當前是串口設備是關閉狀態
{
try
{
timer3.Enabled= true;
serialPort.PortName = com_value.Text;
serialPort.BaudRate = Convert.ToInt32(rate_value.Text);
serialPort.Open();
display2.BackColor = Color.Lime; //將串口開關按鍵的顏色,改為紅色
usart_connet.Text = "關閉串口"; //將串口開關按鍵的文字改為“關閉串口”
usart_connet_display.Text = "串口已連接!";
}
catch
{
MessageBox.Show("打開串口失敗,請檢查串口", "錯誤"); //彈出錯誤對話框
}
}
else //如果當前串口設備是打開狀態
{
try
{
serialPort.Close(); //關閉串口
display2.BackColor = Color.Red; //將串口開關按鍵的顏色,改為青綠色
usart_connet.Text = "打開串口"; //將串口開關按鍵的文字改為 “打開串口”
usart_connet_display.Text = "串口已斷開!";
}
catch
{
MessageBox.Show("關閉串口失敗,請檢查串口", "錯誤");
}
}
}
//串口接收事件
private void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string str = serialPort.ReadExisting(); //讀取資料
textBox2.AppendText(str); //接收框顯示接收到資料
}
/*串口發送事件*/
private void w3_send_Click(object sender, EventArgs e)
{
byte[] bte = { 90, 90, 15, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204 };
try
{
serialPort.Write(bte, 0, 15);//串口發送資料
}
catch
{
MessageBox.Show("發送失敗,請檢查串口是否正常!");
}
}
private void timer3_Tick(object sender, EventArgs e)
{
timer3.Interval = 300;
w3_send_Click(null,null);
}
我是定了一個timer定時向下位機發送資料,下位機收到后回傳資料并在串口工具顯示,現在問題是互動一會后,下位機發出的資料串口助手收不到了,不進DataReceived事件了。
急急急。。。請高手指教。
uj5u.com熱心網友回復:
timer3.Interval = 300;是不是 頻率太高了。。。
uj5u.com熱心網友回復:
300還可以吧,之前做過一個定時發送的,100以下都是沒問題的uj5u.com熱心網友回復:
你這里面不報錯嗎//串口接收事件
private void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string str = serialPort.ReadExisting(); //讀取資料
textBox2.AppendText(str); //接收框顯示接收到資料
}
uj5u.com熱心網友回復:
我這里沒報錯呀uj5u.com熱心網友回復:
1、設備是否真的回復了資料?可以開個監控串口的軟體看看,如CommMonitor;2、你是否發了資料,也可以通過監控軟體看;
3、無資料接收時,串口是否正常。可通過其它軟體開關看看。
如果都沒有問題,那再找代碼的問題吧。
uj5u.com熱心網友回復:
1.2條當時已經驗證了,設備端確實收到了資料并且回傳了。第3條串口工具能發送,接收出問題了,開關串口也不恢復。uj5u.com熱心網友回復:
這個軟體工具我是把客戶端功能和串口功能合并了。我發現不連接服務器,串口功能正常,連接服務器后,一段時間后串口不進接收了。uj5u.com熱心網友回復:
textBox2.AppendText(str); //接收框顯示接收到資料serialPort1.DiscardInBuffer();
serialPort1.DiscardOutBuffer();
這里加個這個試試
uj5u.com熱心網友回復:
猜測是因為某地方的快取滿了嗎?uj5u.com熱心網友回復:
“客戶端功能和串口功能合并”,這句話不懂!uj5u.com熱心網友回復:
這個工具需要與服務器通信和串口通信uj5u.com熱心網友回復:
現在問題是斷開與服務器的鏈接,就能接收到串口的資料了。感覺同時開串口與連接服務器處理的問題很大。uj5u.com熱心網友回復:
你發的代碼不是實際用的代碼吧,是不是用了多執行緒,執行緒是不是死鎖了?uj5u.com熱心網友回復:
與服務器通信是什么介面?uj5u.com熱心網友回復:
把time 改成執行緒uj5u.com熱心網友回復:
學習了!!!!!uj5u.com熱心網友回復:
socket代碼沒附上,socket接收是加了一個新的執行緒處理的uj5u.com熱心網友回復:
socket代碼沒附上,socket的接收是建了一個新的執行緒處理的uj5u.com熱心網友回復:
socket來的uj5u.com熱心網友回復:
附上socket代碼:/*主表單*/
private void Form3_Load(object sender, EventArgs e)
{
/*net引數獲取*/
ip_value.Text = str_ip;
port_value.Text = str_port;
/*客戶端接收函式配置*/
Control.CheckForIllegalCrossThreadCalls = false;
aTimer.Enabled = false;
Thread thread1 = new Thread(TimerMange);
thread1.IsBackground = true;
thread1.Start();
}
/*客戶端接收處理*/
System.Timers.Timer aTimer = new System.Timers.Timer();
void TimerMange()
{
aTimer.Elapsed += new ElapsedEventHandler(socket_rev); //定時事件的方法
aTimer.Interval = 100;
}
byte[] res = new byte[1024];
private void socket_rev(object sender, EventArgs e)
{
int receiveLength = newclient.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
string stringdata = BitConverter.ToString(res, 0, receiveLength);
//textBox2.AppendText(stringdata); //接收框顯示接收到資料
}
}
/*連接服務器*/
private void w3_connet_Click(object sender, EventArgs e)
{
byte[] data = new byte[1024];
string ipadd = ip_value.Text.Trim();//將服務器IP地址存放在字串 ipadd中
int port = Convert.ToInt32(port_value.Text.Trim());//將埠號強制為32位整型,存放在port中
//創建一個套接字
IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ipadd), port);
newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//將套接字與遠程服務器地址相連
try
{
newclient.Connect(ie);
w3_connet.Enabled = false;
aTimer.Enabled = true;
timer2.Interval = 1000;
timer2.Enabled = true; //打開定時器
}
catch
{
MessageBox.Show("連接服務器失敗 ");
return;
}
}
uj5u.com熱心網友回復:
目測是socket_rev這里的問題newclient.Receive(res, res.Length, SocketFlags.None); //這里的代碼會造成同步阻塞,如果服務器不發訊息,會一直阻塞在這里,而且你用的是定時器來觸發這個方法的,估計就是死在這里了,改為執行緒應該可以解決你的問題
uj5u.com熱心網友回復:
現在就是創建了一個新執行緒來處理socket接收的,我試了我定時往服務器發送資料,不讓服務器回傳資料,串口那塊功能還是好用的,說明沒有一直阻塞在那里。你說的方案具體怎么實作呢uj5u.com熱心網友回復:
定時發送是沒問題的,發送不會阻塞執行緒,接收才會1、如何判斷是否阻塞
在newclient.Receive(res, res.Length, SocketFlags.None); 執行前后列印日志,就知道是否阻塞
2、如何判斷阻塞了哪個執行緒
在socket_rev里面輸出 Thread.CurrentThread.Name 就可以知道阻塞哪個執行緒了
3、通常接收訊息,需要用新的執行緒來做,比如
private void doRecieve()
{
byte[] res = new byte[1024];
while (true)
{
int receiveLength = newclient.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
string stringdata = BitConverter.ToString(res, 0, receiveLength);
//textBox2.AppendText(stringdata); //接收框顯示接收到資料
}
else {
//服務器斷開了鏈接
newclient.Close();
break;
}
}
}
啟動新的執行緒
new Thread(new ThreadStart(doRecieve)).Start();
uj5u.com熱心網友回復:
定時發送是沒問題的,發送不會阻塞執行緒,接收才會
1、如何判斷是否阻塞
在newclient.Receive(res, res.Length, SocketFlags.None); 執行前后列印日志,就知道是否阻塞
2、如何判斷阻塞了哪個執行緒
在socket_rev里面輸出 Thread.CurrentThread.Name 就可以知道阻塞哪個執行緒了
3、通常接收訊息,需要用新的執行緒來做,比如
private void doRecieve()
{
byte[] res = new byte[1024];
while (true)
{
int receiveLength = newclient.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
string stringdata = BitConverter.ToString(res, 0, receiveLength);
//textBox2.AppendText(stringdata); //接收框顯示接收到資料
}
else {
//服務器斷開了鏈接
newclient.Close();
break;
}
}
}
啟動新的執行緒
new Thread(new ThreadStart(doRecieve)).Start();
我的代碼中新執行緒加上了定時事件,這個與你寫的有什么區別呢?煩請告知
uj5u.com熱心網友回復:
我記得剛開始做socket用過你這種方法,結果是一直阻塞在newclient.receive中導致界面卡死了。 定時發送是沒問題的,發送不會阻塞執行緒,接收才會
1、如何判斷是否阻塞
在newclient.Receive(res, res.Length, SocketFlags.None); 執行前后列印日志,就知道是否阻塞
2、如何判斷阻塞了哪個執行緒
在socket_rev里面輸出 Thread.CurrentThread.Name 就可以知道阻塞哪個執行緒了
3、通常接收訊息,需要用新的執行緒來做,比如
private void doRecieve()
{
byte[] res = new byte[1024];
while (true)
{
int receiveLength = newclient.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
string stringdata = BitConverter.ToString(res, 0, receiveLength);
//textBox2.AppendText(stringdata); //接收框顯示接收到資料
}
else {
//服務器斷開了鏈接
newclient.Close();
break;
}
}
}
啟動新的執行緒
new Thread(new ThreadStart(doRecieve)).Start();
我的代碼中新執行緒加上了定時事件,這個與你寫的有什么區別呢?煩請告知
用執行緒的話界面不會卡死的,如果界面卡死的話說明運行在主執行緒
你之前碰到的界面卡死已經說明了這個方法是同步阻塞的,用timer觸發同樣會阻塞,只是沒有在主執行緒阻塞而已,如果主機一直不給客戶端發訊息,將會一直阻塞,建議你把詳細日志列印出來 看下先后順序,這樣有助于理解!
uj5u.com熱心網友回復:
附上socket代碼:
/*主表單*/
private void Form3_Load(object sender, EventArgs e)
{
/*net引數獲取*/
ip_value.Text = str_ip;
port_value.Text = str_port;
/*客戶端接收函式配置*/
Control.CheckForIllegalCrossThreadCalls = false;
aTimer.Enabled = false;
Thread thread1 = new Thread(TimerMange);
thread1.IsBackground = true;
thread1.Start();
}
/*客戶端接收處理*/
System.Timers.Timer aTimer = new System.Timers.Timer();
void TimerMange()
{
aTimer.Elapsed += new ElapsedEventHandler(socket_rev); //定時事件的方法
aTimer.Interval = 100;
}
byte[] res = new byte[1024];
private void socket_rev(object sender, EventArgs e)
{
int receiveLength = newclient.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
string stringdata = BitConverter.ToString(res, 0, receiveLength);
//textBox2.AppendText(stringdata); //接收框顯示接收到資料
}
}
/*連接服務器*/
private void w3_connet_Click(object sender, EventArgs e)
{
byte[] data = new byte[1024];
string ipadd = ip_value.Text.Trim();//將服務器IP地址存放在字串 ipadd中
int port = Convert.ToInt32(port_value.Text.Trim());//將埠號強制為32位整型,存放在port中
//創建一個套接字
IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ipadd), port);
newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//將套接字與遠程服務器地址相連
try
{
newclient.Connect(ie);
w3_connet.Enabled = false;
aTimer.Enabled = true;
timer2.Interval = 1000;
timer2.Enabled = true; //打開定時器
}
catch
{
MessageBox.Show("連接服務器失敗 ");
return;
}
}
1、首先Thread 執行緒在你這代碼里沒有任何作用,起作用的還是你的Timer
2、newclient.Receive(res, res.Length, SocketFlags.None);如果你這方法是同步阻塞方法,服務沒有發送資訊,它一直阻塞,那么你的timer會每隔一秒呼叫一次,空閑多少秒就會呼叫多少次。在沒有同步互斥鎖的情況下這里可能會發生例外。
3、建議不用timer來做這個作業,你用執行緒,加sleep。
uj5u.com熱心網友回復:
我記得剛開始做socket用過你這種方法,結果是一直阻塞在newclient.receive中導致界面卡死了。 定時發送是沒問題的,發送不會阻塞執行緒,接收才會
1、如何判斷是否阻塞
在newclient.Receive(res, res.Length, SocketFlags.None); 執行前后列印日志,就知道是否阻塞
2、如何判斷阻塞了哪個執行緒
在socket_rev里面輸出 Thread.CurrentThread.Name 就可以知道阻塞哪個執行緒了
3、通常接收訊息,需要用新的執行緒來做,比如
private void doRecieve()
{
byte[] res = new byte[1024];
while (true)
{
int receiveLength = newclient.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
string stringdata = BitConverter.ToString(res, 0, receiveLength);
//textBox2.AppendText(stringdata); //接收框顯示接收到資料
}
else {
//服務器斷開了鏈接
newclient.Close();
break;
}
}
}
啟動新的執行緒
new Thread(new ThreadStart(doRecieve)).Start();
我的代碼中新執行緒加上了定時事件,這個與你寫的有什么區別呢?煩請告知
用執行緒的話界面不會卡死的,如果界面卡死的話說明運行在主執行緒
你之前碰到的界面卡死已經說明了這個方法是同步阻塞的,用timer觸發同樣會阻塞,只是沒有在主執行緒阻塞而已,如果主機一直不給客戶端發訊息,將會一直阻塞,建議你把詳細日志列印出來 看下先后順序,這樣有助于理解!
uj5u.com熱心網友回復:
附上socket代碼:
/*主表單*/
private void Form3_Load(object sender, EventArgs e)
{
/*net引數獲取*/
ip_value.Text = str_ip;
port_value.Text = str_port;
/*客戶端接收函式配置*/
Control.CheckForIllegalCrossThreadCalls = false;
aTimer.Enabled = false;
Thread thread1 = new Thread(TimerMange);
thread1.IsBackground = true;
thread1.Start();
}
/*客戶端接收處理*/
System.Timers.Timer aTimer = new System.Timers.Timer();
void TimerMange()
{
aTimer.Elapsed += new ElapsedEventHandler(socket_rev); //定時事件的方法
aTimer.Interval = 100;
}
byte[] res = new byte[1024];
private void socket_rev(object sender, EventArgs e)
{
int receiveLength = newclient.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
string stringdata = BitConverter.ToString(res, 0, receiveLength);
//textBox2.AppendText(stringdata); //接收框顯示接收到資料
}
}
/*連接服務器*/
private void w3_connet_Click(object sender, EventArgs e)
{
byte[] data = new byte[1024];
string ipadd = ip_value.Text.Trim();//將服務器IP地址存放在字串 ipadd中
int port = Convert.ToInt32(port_value.Text.Trim());//將埠號強制為32位整型,存放在port中
//創建一個套接字
IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ipadd), port);
newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//將套接字與遠程服務器地址相連
try
{
newclient.Connect(ie);
w3_connet.Enabled = false;
aTimer.Enabled = true;
timer2.Interval = 1000;
timer2.Enabled = true; //打開定時器
}
catch
{
MessageBox.Show("連接服務器失敗 ");
return;
}
}
1、首先Thread 執行緒在你這代碼里沒有任何作用,起作用的還是你的Timer
2、newclient.Receive(res, res.Length, SocketFlags.None);如果你這方法是同步阻塞方法,服務沒有發送資訊,它一直阻塞,那么你的timer會每隔一秒呼叫一次,空閑多少秒就會呼叫多少次。在沒有同步互斥鎖的情況下這里可能會發生例外。
3、建議不用timer來做這個作業,你用執行緒,加sleep。
uj5u.com熱心網友回復:
根據大然然道德帝最高指示,這個問題我們不能參與討論,因為我們一旦參與討論,大然然道德帝就會說我們鄙視新人,打壓新人滴。因為我們接下來要說的話是大然然道德帝,所無法理解覺著所以打擊新人的話
因為你這貼這么多天了,實在看著難受啊。
問題:
1.同步和異步(根據大然然道德帝最高指示,我們無法說先讓你看什么是同步和異步的資料)
2.隔離設計(根據大然然道德帝最高指示,我們無法說先讓你看隔離設計的資料)
1.首先說隔離設計
一個串口+一個socket 屬于橋接設計(根據大然然道德帝最高指示,此處違規,這是鄙視你不懂橋接)
他們應該獨立設計互不干擾,每一個拿出來都應該能獨立運作
訊息傳遞隔離----------使用佇列,rx,eventbus作為通訊橋接(原始上設計模式的橋接有另外的解釋,但我們程式員其實并不拘泥什么Gof,只要能辦到就不必拘泥什么gof)
2.在說異步
一旦你把兩個分開設計了,那么他天生就應該是異步的,因為互不干擾,你做你的,他做他的。
串口-----收資料---發到佇列--剩下不要管
tcp--------接佇列--------發往服務器
tcp---------接服務器訊息--------發到佇列
串口----------收佇列-----發往串口
串口---------收資料-------發佇列-------剩下不管
最后解決方案。(根據大然然道德帝最高指示,以大然然那種道德帝標準,下面依舊違規屬于轉換討論,但是我們說的是如何最快解決問題,保住你飯碗,你想研究什么socket,iocp一類的技術有時間再弄,現在的問題是怎么解決問題,保住你的KPI)
1.使用dotnetty替換你的socket部分,前面說了,兩部分分開隔離設計,兩部分應該獨立。既然串口你本身已經寫了,目前你無法快速解決和另一的獨立問題,那么使用dotnetty,快速讓兩部分獨立(你自己的那個socket,等專案交了,你有空閑時間研究完成的)
2.使用netmq 行程內通訊,把兩個獨立的組件的訊息傳遞橋接起來
uj5u.com熱心網友回復:
根據大然然道德帝最高指示,這個問題我們不能參與討論,因為我們一旦參與討論,大然然道德帝就會說我們鄙視新人,打壓新人滴。
因為我們接下來要說的話是大然然道德帝,所無法理解覺著所以打擊新人的話
因為你這貼這么多天了,實在看著難受啊。
問題:
1.同步和異步(根據大然然道德帝最高指示,我們無法說先讓你看什么是同步和異步的資料)
2.隔離設計(根據大然然道德帝最高指示,我們無法說先讓你看隔離設計的資料)
1.首先說隔離設計
一個串口+一個socket 屬于橋接設計(根據大然然道德帝最高指示,此處違規,這是鄙視你不懂橋接)
他們應該獨立設計互不干擾,每一個拿出來都應該能獨立運作
訊息傳遞隔離----------使用佇列,rx,eventbus作為通訊橋接(原始上設計模式的橋接有另外的解釋,但我們程式員其實并不拘泥什么Gof,只要能辦到就不必拘泥什么gof)
2.在說異步
一旦你把兩個分開設計了,那么他天生就應該是異步的,因為互不干擾,你做你的,他做他的。
串口-----收資料---發到佇列--剩下不要管
tcp--------接佇列--------發往服務器
tcp---------接服務器訊息--------發到佇列
串口----------收佇列-----發往串口
串口---------收資料-------發佇列-------剩下不管
最后解決方案。(根據大然然道德帝最高指示,以大然然那種道德帝標準,下面依舊違規屬于轉換討論,但是我們說的是如何最快解決問題,保住你飯碗,你想研究什么socket,iocp一類的技術有時間再弄,現在的問題是怎么解決問題,保住你的KPI)
1.使用dotnetty替換你的socket部分,前面說了,兩部分分開隔離設計,兩部分應該獨立。既然串口你本身已經寫了,目前你無法快速解決和另一的獨立問題,那么使用dotnetty,快速讓兩部分獨立(你自己的那個socket,等專案交了,你有空閑時間研究完成的)
2.使用netmq 行程內通訊,把兩個獨立的組件的訊息傳遞橋接起來
最近來得比較少,剛才看了下,用戶大然然的確有一些不合適的言論,但是你可以向管理員反饋,也可以點舉報處理
而不是采用一種“碰瓷”一樣的方式。
大然然和你都違反般規,各自禁言3天。
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
改了按照上述所說的新建執行緒確實有效,一直在跑著,目前沒出現不接受的問題,還會持續壓測驗證。uj5u.com熱心網友回復:
用串口工具測驗好,再寫程式是最佳選擇,不會有問題的!轉載請註明出處,本文鏈接:https://www.uj5u.com/net/44647.html
標籤:C#
上一篇:關于鏈接SQLSERVER資料庫的問題,請大家幫忙看下
下一篇:讀寫注冊表或網路操作就崩潰
