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

請教在執行緒中使用高精度計時器與動態陣列的問題

尚未結案
yoan4560409
一般會員


發表:11
回覆:7
積分:3
註冊:2006-08-04

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-10-15 16:13:32 IP:140.116.xxx.xxx 訂閱
各位前輩好
小弟的程式基本的功能為,當執行緒執行時,會動態產生陣列,並計算值後,
開啟定時器將陣列內的值以固定時間送出,待全部送出後在清除動態產生的陣列,並關閉定時器。

目前遇到的問題是,除非我將其中的變數phase宣告成全域變數,不然無法編譯過。
但是若宣告成全域變數,第一次跑執行緒時ok,但再執行此執行緒時會有問題,因為
變數phase被delete不會再產生。
請教各位前輩

1. 我該如何將在執行緒執行時才動態產生的變數,給我的定時器函數使用?
2.或是有更好的寫法?

謝謝

[code cpp]
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
#include "mmsystem.h" //多媒體定時棄檔頭
#pragma package(smart_init)

#define Min(x,y) ((x < y) ? x : y)
#define Max(x,y) ((x > y) ? x : y)
#define Accuracy 1 //最小精度


UINT TimerID; //定義定時器
int TimerAccuracy;
int count=0 ;
//---------------------------------------------------------------------------


__fastcall TTest::TTest(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void TTest::SetName()
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = "Test";
info.dwThreadID = -1;
info.dwFlags = 0;
__try
{
RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD),(DWORD*)&info );
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}
//---------------------------------------------------------------------------
//---------定時器執行內容------------------
void PASCAL TimerCallProc(UINT TimerID, UINT msg,DWORD dwUser,DWORD dwa,DWORD dwb)
{
Form1->Edit1->Text=(String)phase[count]; //錯誤
if(count==500)
{
delete[] phase; //錯誤
count=0;
timeKillEvent(TimerID); //刪除定時器事件
timeEndPeriod(TimerAccuracy); //清除定時器分辨率
}
count ;
}
//---------------------------------------------------------------------------
void __fastcall TTest::Execute()
{
SetName();
//---- Place thread code here ----

float* phase=new float[10000];
for(int i=0;i<500;i ) phase[i]=i;
TIMECAPS timecaps;
if (timeGetDevCaps(&timecaps,sizeof(TIMECAPS))==TIMERR_NOERROR) //定時解析度
TimerAccuracy=Min(Max(timecaps.wPeriodMin,Accuracy),timecaps.wPeriodMax);
timeBeginPeriod(TimerAccuracy); // 設定多媒體計時器的解析度
int TimerResolution=10; //設置定時間隔為10毫秒
//產生間隔10毫秒,周期執行的定時器事件;啟動定時器
TimerID = timeSetEvent(TimerResolution,TimerAccuracy,TimerCallProc,1,TIME_PERIODIC);
}
//---------------------------------------------------------------------------

[/code]
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-10-16 17:30:25 IP:203.73.xxx.xxx 訂閱
看了一下你的程式,有一件事你要注意,『在THREAD不可以直接操作非 Thread Safe的元件』
至於什麼是非 Thread Safe的元件,一般來說畫面上的可視元件,如Edit TListBox TComboBox等都是非Thread Safe的元件
若欲知哪些是非 Thread Safe的元件,請善用站內搜尋功能,因為那又是一大篇文章

所以除非你的 timeSetEvent 有切回MainThread或有呼叫 Synchronize 不然你這種寫法是有問題低
至於為什麼不行,站內有一卡車的討論,請善用站內搜尋功能(用Thread 去搜尋)

你的問題在於,你要怎麼把 TTest::Execute() 下所產生的變數傳遞至TimerCallProc

最簡單的作法就是利用 SendMessage
在產生THREAD時順便把FORM的HANDLE傳入,如下

[code cpp]
__fastcall TTest::TTest(bool CreateSuspended,Handle frmHandle)
: TThread(CreateSuspended)
{
FormHandle = frmHandle; //用一個變數存放 Handle
}

struct Data_struct
{
UINT TimerID;
UINT msg;
DWORD dwUser;
DWORD dwa;
DWORD dwb;
float* phase
};


void __fastcall TTest::Execute()
{
//恕刪....

//用以下的CODE取代原來的timeSetEvent
struct Data_struct Data;

Data.TimerID = TimerResolution;
Data.msg = TimerAccuracy;
Data.dwUser = TimerCallProc;
Data.dwa = 1;
Data.dwb =TIME_PERIODIC;
Data.phase = phase;

SendMessage (FormHandle ,WM_USER 100,(DWORD)&Data,(DWORD)&Data);
}
[/code]


至於FORM對應WM_USER 100 的程式碼.....我想就不用寫了吧

當然有沒有其他的辦法~~有,只是每個人的作法不同,這部分你要多看其他人的CODE
系統時間:2024-04-25 23:19:07
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!