如果在多个子thread中fopen同一文件,fseek不同位置, fwrite(也加过fflush), fclose, 文件大多数都是空白,只有很小部分有内容(进行操作时均使用了临界区)但如果在主thread中多次fopen, 把每个fp传递给多个子thread,然后再fseek到不同位置,再fwrite,最后在主thread中fclose,得到的结果正常。(进行操作时均使用了临界区)why? 有没有高手能解释明白?感激不尽!!!!
注:子thread是用CreateThread开始的,没用_beginthreadex等。
主thread是进程中的主thread.

解决方案 »

  1.   

    TO  ymbymb
    太长了,实在整理不出简短的代码来。TO jink
    谢谢提醒,回去看看~~~~~~
      

  2.   

    TO GodInNight(夜游神) 你似乎没有看清楚我的问题.
    我的所由代码都在一个进程中, 不存在"句柄是进程级"的问题.
    还有,我三年前就在CSDN里了, VB版中我是二星专家(是两年前获得的)
    平时事很多,只能去VB版回答一些比较简单的问题, VC版来的不多, 但也有几千专家分.
    前段时间事更多了, 以至无暇光顾CSDN, 最近空闲下来才回来看看.如果你怀疑我是倒分, 你可以搜索一下我所有的问题 , 看看我的分到底给了谁.
    顺便告诉你怎么看, 在搜索里 主题 中输入一个空格, 作者中填入chice_wxg, 
    你搜一下就知道了.当然,如果你能解决这个问题, 分自然是你的. 我也可以另开贴子给分,我还有5000多
    可用分,你想要多少我都给你----前提是你能解决这个问题.
      

  3.   

    建议你把关键的几个函数调用贴出来,比如fopen的打开方式等。
      

  4.   

    我抽空整理了点代码,大家看看:写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;
    }
      

  5.   

    晕~~~~~~~~这代码已经打开并写文件了(ThreadProc中), 但结果不正确。
    理论上test.bin应该全部有内容的。实际却不是。麻烦各位高手帮忙Debug      :)解决后另送200分。
      

  6.   

    有一点你没搞清楚,文件只能seek 读,没有seek 写!还有一个你的错误处在于 fopen(filename,"w")会把原来的文件破坏,全删了。
      

  7.   

    文件seek写,用fopen方式可以用一个缓冲文件实现,我可以做这样一个类给你,做到线程安全,只要你答应“我要多少分给多少分”。呵呵。我只有两颗三角,实在很弱。不过你再给我200分,我就三个三角了。:-)
      

  8.   

    另外,就算你不用CreateFile,_beginthread,你的Windows下多线程程序往其他OS(比如Unix)移植也是很困难。这一点倒没有你想象的简单。Unix/linux一般都支持POSIX多线程标准,但windows到目前为止是不支持。
      

  9.   

    Opens an empty file for writing. If the given file exists, its contents are destroyed.如果是独占打开的话,其也线程根本打不开。
    说明,你只有一个线程在写这个文件。当然,只有一个线程写的结果。
      

  10.   

    如果想在多线程和多进程同时打开同一个文件,而且保持相互能够使用,应该是_fsopen吧。
      

  11.   

    这就是我想问的,很多情况下是可以保证写完一个文件的。
    以下代码几乎没变,但可以正确建立一个文件: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"); Sleep(100);  //Here!!!//难道说等待所有thread把文件都"wb"打开了然后再一起写就正常了?
    //不知道MSCLib和Windows是如何处理这种情况的? 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);
    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;
    }
    高手指点,谢谢~~~~~~~~~~~
      

  12.   

    还有,如果用param->fp = fopen("C:\\test.bin", "ab+");
    安全吗?TO GodInNight(夜游神) 
    其实线程等部分的代码我早就做好了。
    而且我已经用另一种方法,也解决文件问题,我的程序已经可以同时
    在Linux/Win32上正常工作了。只是遇到了这个问题很奇怪,所以我才会来问。我对多线程编程了解也不是很深,希望高手帮忙指点指点~~~~~
      

  13.   

    fopen 用"wb" 打开文件失会把文件内容清空, 这样当你的第10个线程打开文件时
    前面的线程写入的数据都被清空了, 而之后再写入的数据就保留了下来,所以只有一小部分数据,而且每次都不一样, 改用_open, _lseek, _write就可以了.
    下面是MSDN的原话:
    "w"
    Opens an empty file for writing. If the given file exists, its contents are destroyed.
      

  14.   

    TO  ymbymb(毛病大哥)谢谢关注,不过不知道你是否测试了楼上的楼上的那个代码?结果完全正常。
      

  15.   

    刚才使用上面的代码修改了一下fopen,就可以了。把fopen改成:
    param->fp = _fsopen("C:\\test.bin", "ab", _SH_DENYNO);
      

  16.   

    他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;
    }
      

  17.   

    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;
    }
      

  18.   

    hehe ...
    觉得上面的还是有问题(打开的文件在多线程中会存在争用,特别是文件指针)
    用内存仰射文件应该要来的爽一些
      

  19.   

    hehe , 我个人也不很赞成只有一个文件指针的方法。
    还有就是_fsopen或内存Mapping无法在Linux下实现
    其实我现在是使用 fopen( , "rb+") 来操作的。只是很奇怪fopen("wb")的时候系统的行为。其实到现在我也不是很明白。本来想看看crt库是如何实现的,结果看了就头疼~~~~~~~~谢谢各位帮忙,此帖再放一天,然后结帐~~~~~~~~~~~~
      

  20.   

    如果在多个子thread中fopen同一文件,fseek不同位置, fwrite(也加过fflush), fclose, 文件大多数都是空白,只有很小部分有内容(进行操作时均使用了临界区)
    ---------------------
    不用看了……临界区保护的不足