1

長い操作を実行するモデルオブジェクトがあります。これらの操作のいくつかをスレッドで実行して、インターフェイスの応答性を維持したり、2つを一度にダウンロードしたりしようとしていますが、これらの詳細をインターフェイスコードからできるだけ隠したいと思います。AsyncCallライブラリを使用しようとしていますが、問題があります。

type EUpdaterAction = (auFoundCurrentVersion, auFoundUpdateVersion);

type
  TUpdater = class
  public
    procedure loadCurrentVersion();
    procedure notify(action: EUpdaterAction);
  end;

procedure TUpdater.loadCurrentVersion();
begin
  TAsyncCalls.Invoke(procedure 
  begin 
    Assert(Windows.GetCurrentThreadId() <> System.MainThreadID);
    //Really long code
    TAsyncCalls.VCLSync(procedure begin notify(auFoundCurrentVersion); end);
  end);
end;

アサーションは失敗します。別のスレッドで実行するために何かをする必要がありますか、それともライブラリで示されている最初の例は実際にはスレッドで実行されませんか?

4

2 に答える 2

6

IAsyncCall.ForceDifferentThreadコードを別のスレッドで実行するには、を呼び出す必要があります。この例では、TAsyncCalls.Invoke()が返すインターフェイスは、関数が終了し、IAsyncCallインターフェイスを解放するとSyncメソッドが呼び出されるため、すぐに解放されます。また、タスクはまだ開始されていないため、メソッドが呼び出されSyncない限り、メソッドは同じスレッドでタスクを実行します。ForceDifferentThread

TAsyncCalls.Invoke(procedure 
begin 
  Assert(Windows.GetCurrentThreadId() <> System.MainThreadID);
  //Really long code
  TAsyncCalls.VCLSync(procedure begin notify(auFoundCurrentVersion); end);
end).ForceDifferentThread; // <<<<<

しかし、それは本当にあなたが望むものですか?loadCurrentVersion()が終了した後も、スレッドを存続させたいと思います。そして、このためにAsyncCallsは適切なツールではありません。

于 2012-09-08T17:58:18.950 に答える
1

それはすでにSOで議論されました。InvokeAsyncCallsを呼び出すと、コードが実行されるキューに入れられます。やや遅れて、Asyncallsはコードを実行するためのワーカースレッドを見つけますが、ワーカースレッドがコードに割り当てられるSync 前にForceDifferentThread(そして使用せずに)コードが呼び出された場合、AsyncCallsはコードをキューから削除し、メインスレッドで実行します。これは仕様によるものです。

于 2012-09-08T18:28:28.753 に答える