線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2471
推到 Plurk!
推到 Facebook!

在multithread中fwrite出錯,有解決方法嗎?  

尚未結案
weken
一般會員


發表:8
回覆:4
積分:2
註冊:2007-06-28

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-12-09 19:44:10 IP:118.169.xxx.xxx 訂閱
在程式中建立許多THREAD
每個THREAD透過comport接收外部設備的資料,然後將收到的資料用fwrite寫入檔案(每個thread 的 fp不同,檔名不同)
卻發現同時間寫不同檔案時,有些資料會遺失
經研判可能是THREAD A寫完後,換THREAD B寫,但硬碟動作比thread 的速度慢
因此會造成資料的遺失

我不知道這樣的判斷正不正確
可否請有經驗的人幫忙回答一下

謝謝
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-12-10 20:24:33 IP:60.248.xxx.xxx 訂閱
你好,
你這題目與上回所問的應該是同一個問題。因近來很忙,所以上回回覆你之後就沒有再接下去了…

照我的看法,你有二個方法可以試。
1/ 使用criticalsection 或是其他sync的方式,於寫之前先lock一下。
2/ 使用setvbuf (fp, NULL, _IONBF, 0); 函式來處理看看,這必需要放在
fp=fopen(FName.c_str(),"ab ");之後,write 之前。

希望可以解決問題,若ok,則另一個問題也就請結案了,謝謝!
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
weken
一般會員


發表:8
回覆:4
積分:2
註冊:2007-06-28

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-12-12 15:40:35 IP:210.68.xxx.xxx 訂閱
不好意思,我想再請問一下

thread的宣告是
Tthread *MyThread[100];

在每個Thread之中都有用到fwrite的動作
而變數我都宣告在建構的時候

class Tthread : public TThread
{
private:
void SetName();
HANDLE hCom;
AnsiString F_Name;
FILE *fp;
}
程式的架構是
1.建立thread
2.連結外部裝備
3.將外部資訊寫檔

步驟 1 -> 步驟2 -> 步驟3 -> 步驟 1 -> 步驟2 -> 步驟3
當thread 1 開啟,且執行,會不斷的接收外部資料然後寫檔
這時候開啟thread 2,理論上thread 2會擁有自己的fp,且thread1依舊會執行
但thread 1的fp好像會被thread 2所甘擾到而出錯

但步驟 1 ,運行兩次,再去做步驟2
即thread 1 和 thread2 先建構後,再去做接收外部資料寫檔的動作就不會出錯

可否請問這是什麼問題?或是變數不應如此宣告?



aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-12-12 18:07:15 IP:60.248.xxx.xxx 訂閱
你好, 不知你是否已經試過我講的第二個方法

你的問題可能性有二個,因為沒看到完整程式碼,所以也無法定論。

fwrite 是buffer性 的輸入,在同一個process裡buffer可能會共用。buffer的意思是並沒一fwrite就會寫入檔案,而是暫放在buffer,等一定程式的滿後,才寫入harddisk。也因此我建議你使用非buffer的寫入法方。而你說的但步驟 1 ,運行兩次,再去做步驟2,是否有可能因時間搓開了,所以感覺沒問題… 還是請你先測我說的方法2。

此外,我看你的thread雖然是要開100個,但每個thread其實是同一種thread,不知你如何讓寫入的檔名有所不同? 因為你的建構式中也沒有參數型式讓你設定檔名。像我的做法會是

public:
__fastcall Tthread (AnsiString file_name);

在主程式中new的時候把不同的名字傳入上述的建構式上

你是如何實現的? 我想會不會有可能有問題?

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
weken
一般會員


發表:8
回覆:4
積分:2
註冊:2007-06-28

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-12-13 11:28:25 IP:118.169.xxx.xxx 訂閱
你好
我的檔名是用 __fastcall Tthread (AnsiString file_name);這種方式傳入
謝謝你

另外我想請問一些基本的問題
__fastcall Tthread (AnsiString file_name)
{
char c;
int a
}

thread::execute()
{
char c;
int a;
}

char c;
int a;
thread::execute()
{
.......
}
這三種變數的宣告方式
第一種和第二種的變數是不是每個thread獨有,不會互相衝突
第三種是不是會被所有的thread共用,而互相衝突到呢?
假設會互相衝突
那execute後跑到Synchronize(),我要如何宣告一個公共變數給Synchronize使用呢?(每個thread必須獨立,不互相干擾)

謝謝回答
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-12-13 14:50:40 IP:59.115.xxx.xxx 訂閱


>>第一種和第二種的變數是不是每個thread獨有,不會互相衝突
是,是個自獨有。

>>第三種是不是會被所有的thread共用,而互相衝突到呢?
是,會互相衝突


>>那execute後跑到Synchronize(),我要如何宣告一個公共變數給Synchronize使用呢?(每個thread必須獨立,不互相干擾)
你的這個意思不我太明白。若你希望在Synchronize(foo);
而foo這個方法如下: (舉例)

int for_sync_only_var; //專給sync用的

void __fastcall Tthread::foo()
{
//for_sync_only_var = k; //這樣也可以,假設k是Tthread裡的資料成員,資料成員是每個thread個自有的。
for_sync_only_var = 7;
Form1->Label1->Text = IntToStr(for_sync_only_var);
}

若for_sync_only_var這個變數永遠只會出現在synchronize,不會用別的方法來修改取用,那麼就算是thread-safe的。

請參考我部落格裡的thread-safe一文:
http://aftcast.pixnet.net/blog/post/23786004
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
系統時間:2017-10-17 7:58:37
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!