thread中使用fwrite等C Lib函数的问题。

Chice_wxg 2004-04-27 11:59:22
如果在多个子thread中fopen同一文件,fseek不同位置, fwrite(也加过fflush), fclose, 文件大多数都是空白,只有很小部分有内容(进行操作时均使用了临界区)

但如果在主thread中多次fopen, 把每个fp传递给多个子thread,然后再fseek到不同位置,再fwrite,最后在主thread中fclose,得到的结果正常。(进行操作时均使用了临界区)

why? 有没有高手能解释明白?感激不尽!!!!


注:子thread是用CreateThread开始的,没用_beginthreadex等。
主thread是进程中的主thread.
...全文
174 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
icanfeeling 2004-04-30
  • 打赏
  • 举报
回复
如果在多个子thread中fopen同一文件,fseek不同位置, fwrite(也加过fflush), fclose, 文件大多数都是空白,只有很小部分有内容(进行操作时均使用了临界区)
---------------------
不用看了……临界区保护的不足
mzg3 2004-04-29
  • 打赏
  • 举报
回复
楼上的没错
应该如此
不明白楼主为何要在每个线程中使用一个单独打开的文件指针
ymbymb 2004-04-29
  • 打赏
  • 举报
回复
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
char buf[100];
int i;
PARAM *param = (PARAM *)lpParam;

for(i=30;i<130;i++)
buf[i - 30] = i;
if(param->fp)
{
for(i=0;i<100;i++)
{
EnterCriticalSection(&cs);
fseek(param->fp, param->idx * 10000 + i*100, SEEK_SET);
fwrite(buf, 100, 1, param->fp);
fflush(param->fp);
LeaveCriticalSection(&cs);
}

printf("Thread %d finished.\r\n", param->idx);
}
else
{
printf("Thread %d FILE ERROR!\r\n", param->idx);
}

delete param;

return 0;
}
ymbymb 2004-04-29
  • 打赏
  • 举报
回复
他Sleep的目的就是让所有的线程都创建好并且执行完fopen, 这样再写入数据就不会丢失, 但是这种方法很不可靠, 换台机器或换个系统也许就不对了,其实比较好的方法是,在Main里打开文件, 创建线程, 把文件ID传递给线程, 然后在线程里写文件, 最后在Main里再关闭线程.
int main(int argc, char* argv[])
{
PARAM *param;
DeleteFile("C:\\test.bin");

InitializeCriticalSection(&cs);
FILE *fp = fopen("C:\\test.bin", "wb");

for(int i=0;i<10;i++)
{
param = new PARAM;
param->fp = fp;
param->idx = i;
CreateThread(NULL, 0, ThreadProc, param, 0, NULL);
}
puts("Wait for threads to finish");
getch();
DeleteCriticalSection(&cs);
fclose(fp);
return 0;
}
tuyang 2004-04-29
  • 打赏
  • 举报
回复
刚才使用上面的代码修改了一下fopen,就可以了。把fopen改成:
param->fp = _fsopen("C:\\test.bin", "ab", _SH_DENYNO);
Chice_wxg 2004-04-29
  • 打赏
  • 举报
回复


hehe , 我个人也不很赞成只有一个文件指针的方法。


还有就是_fsopen或内存Mapping无法在Linux下实现


其实我现在是使用 fopen( , "rb+") 来操作的。

只是很奇怪fopen("wb")的时候系统的行为。

其实到现在我也不是很明白。本来想看看crt库是如何实现的,结果看了就头疼~~~~~~~~



谢谢各位帮忙,

此帖再放一天,然后结帐~~~~~~~~~~~~
mzg3 2004-04-29
  • 打赏
  • 举报
回复
hehe ...
觉得上面的还是有问题(打开的文件在多线程中会存在争用,特别是文件指针)
用内存仰射文件应该要来的爽一些
tuyang 2004-04-28
  • 打赏
  • 举报
回复
如果想在多线程和多进程同时打开同一个文件,而且保持相互能够使用,应该是_fsopen吧。
GodInNight 2004-04-28
  • 打赏
  • 举报
回复
同一进程的多线程同时打开同一文件应该可以的。多进程就难说了。
UDX协议 2004-04-28
  • 打赏
  • 举报
回复
Opens an empty file for writing. If the given file exists, its contents are destroyed.

如果是独占打开的话,其也线程根本打不开。
说明,你只有一个线程在写这个文件。当然,只有一个线程写的结果。
GodInNight 2004-04-28
  • 打赏
  • 举报
回复
另外,就算你不用CreateFile,_beginthread,你的Windows下多线程程序往其他OS(比如Unix)移植也是很困难。这一点倒没有你想象的简单。

Unix/linux一般都支持POSIX多线程标准,但windows到目前为止是不支持。
GodInNight 2004-04-28
  • 打赏
  • 举报
回复
文件seek写,用fopen方式可以用一个缓冲文件实现,我可以做这样一个类给你,做到线程安全,只要你答应“我要多少分给多少分”。呵呵。

我只有两颗三角,实在很弱。不过你再给我200分,我就三个三角了。:-)
nik_Amis 2004-04-28
  • 打赏
  • 举报
回复
u[p
GodInNight 2004-04-28
  • 打赏
  • 举报
回复
不服的话再说
GodInNight 2004-04-28
  • 打赏
  • 举报
回复
有一点你没搞清楚,文件只能seek 读,没有seek 写!

还有一个你的错误处在于 fopen(filename,"w")会把原来的文件破坏,全删了。

Chice_wxg 2004-04-28
  • 打赏
  • 举报
回复
晕~~~~~~~~

这代码已经打开并写文件了(ThreadProc中), 但结果不正确。
理论上test.bin应该全部有内容的。实际却不是。



麻烦各位高手帮忙Debug :)

解决后另送200分。
ymbymb 2004-04-28
  • 打赏
  • 举报
回复
你至少要把你打开文件,写文件的代码帖出来, 不然怎么帮你啊!
Chice_wxg 2004-04-28
  • 打赏
  • 举报
回复
我抽空整理了点代码,大家看看:

写C:\test.bin文件,写完后文件大多部分为空!
而实际填充buf的时候填充的是可见字符。

代码随便改,只要完成这个任务就可以了,不要用CreateFile和_beginthread等Win32特有的函数(临界区和线程控制在其他OS下照样可以实现)。



TO GodInNight(夜游神)
你对自己很自信的话来试试。很多问题远比你想象的复杂。

// ThreadTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>

typedef struct _PARAM
{
FILE *fp;
INT idx;
}PARAM;

CRITICAL_SECTION cs;

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
char buf[100];
int i;
PARAM *param = (PARAM *)lpParam;

for(i=30;i<130;i++)
buf[i - 30] = i;

param->fp = fopen("C:\\test.bin", "wb");

if(param->fp)
{
fseek(param->fp, param->idx * 10000, SEEK_SET);


for(i=0;i<100;i++)
{
EnterCriticalSection(&cs);
fwrite(buf, 100, 1, param->fp);
fflush(param->fp);
LeaveCriticalSection(&cs);
}

printf("Thread %d finished.\r\n", param->idx);
fclose(param->fp);
}
else
{
printf("Thread %d FILE ERROR!\r\n", param->idx);
}

delete param;

return 0;
}


int main(int argc, char* argv[])
{
PARAM *param;
DeleteFile("C:\\test.bin");

InitializeCriticalSection(&cs);

for(int i=0;i<10;i++)
{
param = new PARAM;
param->fp = NULL;
param->idx = i;
CreateThread(NULL, 0, ThreadProc, param, 0, NULL);
}
puts("Wait for threads to finish");
getch();
DeleteCriticalSection(&cs);
return 0;
}

tuyang 2004-04-28
  • 打赏
  • 举报
回复
建议你把关键的几个函数调用贴出来,比如fopen的打开方式等。
Chice_wxg 2004-04-28
  • 打赏
  • 举报
回复
希望你没有测试不要轻易下结论。
加载更多回复(13)

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧