全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4383
推到 Plurk!
推到 Facebook!

不知道這樣的ReadFile和WriteFile控制USB會不會有問題?

答題得分者是:taishyang
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-06-30 16:32:43 IP:203.75.xxx.xxx 訂閱
因為現在我所控制的USB裝置使用了一段時間後會發生「系統資源不足」的問題,看來看去,不知道哪邊有問題。

但前輩寫的USB READ/WRITE的流程和我所看過的範例不太一樣,還請各位看看這樣的流程有沒有問題

1. 在MAIN做CreateFile取得READ和WRITE的HANDLE
==============程式片段===================
if(bIn)
{
hDevice = CreateFile(pDeviceDetail->DevicePath,
GENERIC_READ, // read // Device ==> PC
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
}
else
{
hDevice = CreateFile(pDeviceDetail->DevicePath,
GENERIC_WRITE, // write // PC ==> Device
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
}
free(pDeviceDetail);
return hDevice;
==============程式片段結束===================

2. 建立一個執行緒,持續讀取裝置及處理所得到的資料
==============程式片段===================
void __fastcall TfmUsbMain::GetHidData(void)
{
if(!GetReport())
return;
//以下處理過程省略
}

bool __fastcall TfmUsbMain::GetReport(void)
{
bool bResult = false;
unsigned long ulBytes = 0;

bResult=ReadFileEx(DeviceInHandle,
USBDataIn,
17,
(LPOVERLAPPED) &ulBytes,
(LPOVERLAPPED_COMPLETION_ROUTINE) &osRead);

return bResult;
}
==============程式片段結束===================

3. 執行緒做它的事情,我仍然可以使用writefile到裝置中
==============程式片段===================
bool __fastcall TfmUsbMain::SetReport(void)
{
HidReadThread->Suspend();
bool bResult = true;
BYTE byBuf[17];
unsigned long ulBytes = 0;

byBuf[0] = 0; // report ID;
for(int j=1; j<=16; j )
byBuf[j] = ToBoardBuf[j-1];

bResult=WriteFileEx(DeviceOutHandle,
byBuf,
17,
(LPOVERLAPPED) &ulBytes,
(LPOVERLAPPED_COMPLETION_ROUTINE) &osWrite); //Tony, Write 1 16 bytes for 16 bytes pipe

if(!bResult)
{
//處理要做的事情
}
HidReadThread->Resume();
return bResult;
}
==============程式片段結束===================

以上就是程式對USB的控制流程。

因為程式執行的過程中,必須時時檢查裝置有無訊號進來,
所以只有在關閉程式的時候才會執行CloseHandle的工作。

但時間久了,就會發生「系統資源不足」的問題。
不知道與這段程式是否有所關連?
編輯記錄
GrandRURU 重新編輯於 2010-06-30 16:33:45, 註解 無‧
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-06-30 17:19:21 IP:122.116.xxx.xxx 訂閱
執行緒裡面做了什麼事情嗎?
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-06-30 23:06:39 IP:111.249.xxx.xxx 訂閱
ReadFile的執行緒:
void __fastcall THidReadThread::Execute()
{
while(!Terminated)
{
Sleep(10);
fmManager->pfmUsbMain->GetHidData();
}
}

GetHidData函式詳細內容:
void __fastcall TfmUsbMain::GetHidData(void)
{
if(!GetReport())
return;

unsigned short myData;

bGetReportProcessing = true;
ShowGetDataTimer->Enabled = true;

if(bManyTones)
{
ReceiveManyTones();
if(tempGetDT_Count >= GetDT_Count)
{
bManyTones = false;
StaticTextReceiveToneContent->Caption = "";
for(unsigned int j=0; j {
StaticTextReceiveToneContent->Caption = StaticTextReceiveToneContent->Caption
ConvertTone(GetDT_Buf[j]);
}
LblRecieveToneStatus->Visible = false;
ToUI("UIGetTone", StaticTextReceiveToneContent->Caption);
}
return;
}
else
{
bManyTones = CheckManyTones();
UpdateGet1Tone();
UpdateKeyStatus();
UpdateBoardStatus();
UpdateSendToneMessage();

bGetReportProcessing = false;
}
}
GetReport詳細內容:
bool __fastcall TfmUsbMain::GetReport(void)
{
bool bResult = false;
unsigned long ulBytes = 0;

//bResult=ReadFile(DeviceInHandle, USBDataIn, 17, &ulBytes, NULL);
bResult=ReadFileEx(DeviceInHandle,
USBDataIn,
17,
(LPOVERLAPPED) &ulBytes,
(LPOVERLAPPED_COMPLETION_ROUTINE) NULL);

return bResult;
}

以上就是執行緒會經過的地方,不知道對分析有沒有幫助 @@;
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#4 引用回覆 回覆 發表時間:2010-06-30 23:57:41 IP:114.37.xxx.xxx 訂閱
若執行緒中有用到VCL,必須用同步的機制保護
站上有相關的討論文章

GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-07-01 00:01:56 IP:111.249.xxx.xxx 訂閱
在這邊的vcl元件是獨立給一個執行緒使用
請問…這樣還需要同步嗎?

還是說不同步的情況下會導致系統資源不足的問題嗎?

編輯記錄
GrandRURU 重新編輯於 2010-07-01 00:03:51, 註解 無‧
GrandRURU 重新編輯於 2010-07-01 00:04:32, 註解 無‧
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-07-01 00:24:55 IP:114.37.xxx.xxx 訂閱
個人經驗是,若有刷新畫面的情況且沒有同步保護的話,會有資源不足的問題^^
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-07-01 09:20:36 IP:203.75.xxx.xxx 訂閱
 因為有8個執行緒在跑,如果用Synchronize,會卡住main

所以現在是用PostMessage在測,不知道這樣的方法行不行得通?
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-07-01 10:07:49 IP:122.116.xxx.xxx 訂閱
那你可能還是得用WaitForSingleObject or WaitForMultipleObjects來做保護
一開始也沒提到總共有8個thread在run,要不要先確認是否是USB這邊的thread所造成^^?
編輯記錄
taishyang 重新編輯於 2010-07-01 10:09:33, 註解 無‧
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#9 引用回覆 回覆 發表時間:2010-07-02 22:11:04 IP:111.249.xxx.xxx 訂閱
目前在vcl畫面更新的地方以postmessage來代替,但是仍然會當機
usb的thread只會對應到各自的form,所以不會有打架的問題

但資源不足到底是什麼樣的情況才會發生呢?

一旦資源不足,連「開始→程式集」裡面都是空白一片,這還真是糟糕啊…

===================引 用 taishyang 文 章===================
那你可能還是得用WaitForSingleObject or WaitForMultipleObjects來做保護
一開始也沒提到總共有8個thread在run,要不要先確認是否是USB這邊的thread所造成^^?
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#10 引用回覆 回覆 發表時間:2010-07-05 13:33:53 IP:203.75.xxx.xxx 訂閱
PostMessage...真的會有問題,但不知是否為元兇

MSDN上是這樣說的:
There is a limit of 10,000 posted messages per message queue. This limit should be sufficiently large. If your application exceeds the limit, it should be redesigned to avoid consuming so many system resources. To adjust this limit, modify the following registry key.

嗯……
不知道SendMessage是否也會有這樣的問題?MSDN上沒寫。
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#11 引用回覆 回覆 發表時間:2010-07-05 14:38:21 IP:122.116.xxx.xxx 訂閱
SendMessage應該不會,因為會等待ACK
PostMessage不會等待ACK,會一直送
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#12 引用回覆 回覆 發表時間:2010-07-07 16:02:08 IP:203.75.xxx.xxx 訂閱
嗯,跑了兩天,還沒當機,看起來真的是因為PostMessage的問題,目前SendMessage順利運作中
謝謝 Taishyang 版大囉

===================引 用 taishyang 文 章===================
SendMessage應該不會,因為會等待ACK
PostMessage不會等待ACK,會一直送
系統時間:2024-04-23 23:22:46
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!