为什么我的应用程序在复制大文件时会冻结?

时间:2010-02-26 01:55:11

标签: c windows mfc multithreading

我有一个MFC应用程序。基本上只是将文件从一个驱动器复制到另一个驱动器。当我复制大文件(超过1 Gb)并单击我的窗口时,我的应用程序冻结,但复制在后台进行。有人告诉我,我必须使用工作线程。我用它,但它仍然冻结。当我复制小文件时,就可以了。我无法弄清楚可能是什么问题。请有人帮忙!

这是我的代码:

void CGetFileListDlg::OnBnClickedButtonGetFileList()  
{
 //here i'm doing file list comparing
 AfxBeginThread( CopyThread, &Tstruct ); //here i call my thread and give a struct to it as a paramter, which contains, which file i have to copy
}   

UINT CopyThread( LPVOID pParam )
{
UINT uiMaxPass = 3;
UINT uiPAssCount = 0;
int i = 0;

threadstruct *Test = (threadstruct*)(pParam);
CGetFileListDlg* ptr = (CGetFileListDlg*)Test->ez ;

struct address
{
    char *from;
    char *to;
    int current;
};

struct address Address;


for ( i = 0; i < Test->diff; i++ )
    {

    TCHAR currentfile[512], file[MAX_PATH +32], successf[10], unsuccessf[10], buf[20], remainingf[20], oprog[10];
    char tmp[1024], tmp2[1024],dest[1024];
    int j,k,l;
    char ch;

    memset( tmp, 0, sizeof( tmp ) );
    memset( dest, 0, sizeof( dest ) );
    memset( tmp2, 0, sizeof( tmp2 ) );
    memset( buf, 0, sizeof( buf ) );
    memset( currentfile, 0, sizeof( currentfile ) );
    memset( file, 0, sizeof( file ) );
    memset( successf, 0, sizeof( successf ) );
    memset( unsuccessf, 0, sizeof( unsuccessf ) );
    memset( remainingf, 0, sizeof( remainingf ) );
    memset( oprog, 0, sizeof( oprog ) );
    ch = NULL;
    strcat( dest, SecondaryHDD );

    l = 1;
    for ( k = strlen( SecondaryHDD ); k < strlen( Test->difference[i].filename ); k++ )
    {
        dest[k] = Test->difference[i].filename[ l + strlen( SecondaryHDD ) - 1 ];
        l++;
    }
    dest[k]='\0';

    for ( j = strlen( Test->difference[i].filename); ch != '\\'; j-- )
    {
        ch = Test->difference[i].filename[j];
    }

    l = 0;
    for ( k = 3; k < j + 1; k++ )
    {
        tmp2[l] = Test->difference[i].filename[k];
        l++;
    }
    tmp2[l]='\0';
    strcpy( tmp, SecondaryHDD );
    strcat( tmp, tmp2);

    SHCreateDirectoryExA( NULL, tmp, NULL );

    memset( file, 0, sizeof( file ) );

    memset( tmp, 0, sizeof( tmp ) );
    strcpy(tmp, Test->difference[i].filename );

    MultiByteToWideChar(  CP_ACP, NULL, tmp, -1, file, strlen( Test->difference[i].filename ) );
    wsprintf( currentfile, _T("%s"), file );
    ptr->m_edCurrentCopy.SetWindowText( currentfile );

    Address.from = strdup(tmp);
    Address.to = strdup(dest);
    Address.current = i;

    PostMessage( (HWND)Test->hWnd , WMU_PROGRESS, (WPARAM)&Address, (LPARAM)&dest ); //calling OnProgressMsg function, which does the copy
    Sleep(100);
}

PostMessage( (HWND)Test->hWnd, WMU_COPYDONE, uiPAssCount, 0 );

return 0;
}  

LRESULT CGetFileListDlg::OnProgressMsg( WPARAM wParam, LPARAM lParam )
{ 
    TCHAR currentfile[512], file[MAX_PATH +32], successf[10], unsuccessf[10], buf[20], remainingf[20], oprog[10];
char tmp[1024], tmp2[1024],dest[1024];
int j,k,l;
char ch;
struct address
{
    char *from;
    char *to;
    int current;
};

address *Address = (address*)wParam;

//char *to = (char*)lParam;    
//char *from = (char*)wParam;    

int ret = 0;
ret = CopyFileA( Address->from, Address->to, false );
//ret = CopyFileExA( Address->from, Address->to, &MyCopyProgressRoutine, this, FALSE,FALSE);

if ( ret == 0 ) //failed
{
    wsprintf( buf, _T("Failed ( %d )"), GetLastError() );
    m_difference.SetItemText(Address->current, 2, buf);
    unsuccess++;
    wsprintf( unsuccessf, _T("%d"), unsuccess, GetLastError() );
    m_unsuccess.SetWindowText( unsuccessf );
}
else
{
    m_difference.SetItemText(Address->current, 2, L"OK!");
    success++;
    wsprintf( successf, _T("%d"), success );
    m_success.SetWindowText( successf );
}

wsprintf( remainingf, _T("%d"), ( diff - ( success + unsuccess ) ) );
m_remaining.SetWindowText( remainingf );

wsprintf( oprog, _T("%d %%"), ( (success + unsuccess ) *100 )/diff );
m_overallprog.SetWindowText( oprog );

UpdateData(FALSE);

return 0;
}

2 个答案:

答案 0 :(得分:10)

PostMessage( (HWND)Test->hWnd , WMU_PROGRESS, (WPARAM)&Address, (LPARAM)&dest );
//calling OnProgressMsg function, which does the copy

所以你产生了一个新线程,那个...将消息发布到主线程并让主线程进行所有复制?

那是你如何使用工作线程。您的工作线程应该是进行复制的线程,而OnProgressMsg应该做的就是更新UI。

答案 1 :(得分:1)

我认为使用WorkerThread意味着WorkerThread必须进行复制。至少就Win32API而言,所有Windows,实际上在Windows中都有hWnd句柄,都有一个消息循环。当此消息循环在足够的时间范围内停止响应时,Windows资源管理器认为您的应用程序“没有响应”,因为实质上它不是 - 它不处理消息。

您需要做的是调用执行复制的子线程,然后在完成后通知“父”线程,以便关闭对话框;或通知父对话框进度,以便父对话框可以更新进度条,或类似的东西。