我有一个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;
}
答案 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资源管理器认为您的应用程序“没有响应”,因为实质上它不是 - 它不处理消息。
您需要做的是调用执行复制的子线程,然后在完成后通知“父”线程,以便关闭对话框;或通知父对话框进度,以便父对话框可以更新进度条,或类似的东西。