CnPack Forum » CnVCL 组件包 » CnMD5的进度回调函数怎么使用?


2010-8-25 10:50 yinsim
CnMD5的进度回调函数怎么使用?

[code]
var
  FAbort: Boolean;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FAbort := False;
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
  if dlgOpen1.Execute then
    edt1.Text := MD5Print(MD5File(dlgOpen1.FileName, MD5CalcPrgssProc)));
end;

procedure TForm1.MD5CalcPrgssProc(ATotal, AProgress: Int64;
  var Cancel: Boolean);
begin
  pb1.Position := Round(AProgress / ATotal * 100);
  Cancel := FAbort;
end;[/code]

这里实现了MD5的进度回调函数后,似乎实际调用后进度条没有变化,而实际获取到了文件的MD5值,即使只在回调函数里面只添加一条简单的ShowMessage都不显示,请问为什么?

2010-8-25 13:03 Passion
加个Application.ProcessMessages;试一试?

2010-8-25 14:12 yinsim
谢谢Passion这么快回复,辛苦了!

添加Application.ProcessMessages仍然无效.........

2010-8-25 20:31 Passion
我们做MD5时默认的Buffer大小是4M,也就是进度的粒度是4M,小于4M的文件一次算完了,不会出现进度回调。
因此如果您的文件较小,那么不回调是正常现象。

如果要修改此粒度,可在CnMD5.pas中搜寻并修改 4096 * 1024 这个常量。

2010-8-26 08:13 yinsim
我之前就试过大小文件,即使是几百M的文件,也是这种情况.

另外,按道理调用进度回调时如果把传入的变量CancelCalc为True,则在计算大于4M的文件时,在计算完首个4M后应该要中止才对,但是列程还是会继续,并计算出了正确的MD5值.

百思不得其解啊...

2010-8-26 12:34 Passion
Oh,我看了一下代码,确实有问题。当初我们为提高计算速度,对于大小小于2G的直接进行了文件内存映射,根据内存地址去直接计算,这个直接计算的代码中是没有处理回调的。

如果要修补此问题,可以查找FileSizeIsLargeThan2G(FileName)此处调用改成False,便会用常规方式进行文件的分块读入并计算,此时回调应该有效。Cancel也应该会有效。

2010-8-26 15:43 yinsim
嗯,终于可以有进度回调了,也可以中止了.不过是要将FileSizeIsLargeThan2G(FileName)这里直接改为True,而不是False,要不然还是使用内存映射.

谢谢Passion的耐心回复,另外内存映射方式有无可能也添加进度回调?

2010-8-27 08:24 Passion
也不是不行。不过改动稍微有点大。

页: [1]


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.