CopyFileEx 可以从辅助线程调用吗?

发布于 2024-11-15 16:21:57 字数 192 浏览 6 评论 0原文

是否可以并且正确地从线程调用 CopyFileEx 和 CopyCallback/ProgressRoutine 函数(ProgressBar.Position 将同步)?

我可以在线程中声明 CopyCallback/ProgressRoutine 函数吗?我在 @ProgressRoutine 上的 CopyFileEx 中收到错误:“需要变量”。

Is it possible and right to call CopyFileEx and CopyCallback/ProgressRoutine function (ProgressBar.Position will be synchronized) from a thread?

Can I declare CopyCallback/ProgressRoutine function in a thread? I get Error: "Variable required" in CopyFileEx on @ProgressRoutine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尹雨沫 2024-11-22 16:21:57

当然有可能。回调函数将在调用 CopyFileEx 的线程上下文中调用。如果您需要同步某些 UI 命令,请使用 Delphi 常用的 TThread.Synchronize 或您想要的任何其他线程间同步技术。

回调函数不能是线程类的方法。它需要与 API 指定的签名相匹配,因此它需要是一个独立的函数。当您正确声明它后,将其传递给 CopyFileEx 时就不需要使用 @ 运算符。

function CopyProgressRoutine(TotalFileSize, TotalBytesTransferred: Int64;
  StreamSize, StreamBytesTransferred: Int64;
  dwStreamNumber, dwCallbackReason: DWord;
  hSourceFile, hDestinationFile: THandle;
  lpData: Pointer): DWord; stdcall;

您可以使用 lpData 参数为回调函数提供对关联线程对象的访问权限。调用 CopyFileEx 时,传递对该参数的线程对象的引用:

procedure TCopyThread.Execute;
begin
  ...
  CopyResult := CopyFileEx(CurrentName, NewName, CopyProgressRoutine, Self,
    @Cancel, CopyFlags);
  ...
end;

通过访问线程对象,您可以调用该对象上的方法,包括其自己的进度例程,因此以下内容可以构成整体的独立功能。它可以将其他所有事情委托回对象的方法。在这里,我假设该方法具有与独立函数相同的参数,但它省略了 lpData 参数,因为它将作为 Self 参数隐式传递。

function CopyProgressRoutine;
var
  CopyThread: TCopyThread;
begin
  CopyThread := lpData;
  Result := CopyThread.ProgressRoutine(TotalSize, TotalBytesTransferred,
    StreamSize, StreamBytesTransferred, dwStreamNumber,
    dwCallbackReason, hSourceFile, hDestinationFile);
end;

Of course it's possible. The callback function will be called in the context of the thread that calls CopyFileEx. If you need to synchronize some UI commands, use Delphi's usual TThread.Synchronize, or whatever other inter-thread synchronization techniques you want.

The callback function cannot be a method of the thread class. It needs to match the signature dictated by the API, so it needs to be a standalone function. When you've declared it correctly, you won't need to use the @ operator when you pass it to CopyFileEx.

function CopyProgressRoutine(TotalFileSize, TotalBytesTransferred: Int64;
  StreamSize, StreamBytesTransferred: Int64;
  dwStreamNumber, dwCallbackReason: DWord;
  hSourceFile, hDestinationFile: THandle;
  lpData: Pointer): DWord; stdcall;

You can give the callback function access to the associated thread object with the lpData parameter. Pass a reference to the thread object for that parameter when you call CopyFileEx:

procedure TCopyThread.Execute;
begin
  ...
  CopyResult := CopyFileEx(CurrentName, NewName, CopyProgressRoutine, Self,
    @Cancel, CopyFlags);
  ...
end;

With access to the thread object, you can call methods on that object, including its own progress routine, so the following could constitute the entirety of the standalone function. It can delegate everything else back to a method of your object. Here I've assumed the method has all the same parameters as the standalone function, except that it omits the lpData parameter because that's going to be passed implicitly as the Self parameter.

function CopyProgressRoutine;
var
  CopyThread: TCopyThread;
begin
  CopyThread := lpData;
  Result := CopyThread.ProgressRoutine(TotalSize, TotalBytesTransferred,
    StreamSize, StreamBytesTransferred, dwStreamNumber,
    dwCallbackReason, hSourceFile, hDestinationFile);
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文