あなたの最善の解決策は、スレッドプールスレッドを使用して作業を行うことです。
- ファイルの属性を照会する作業単位を割り当てる
- は、あなたのスレッド関数が完了すると、完了
- から
GetFileAttributes
実行が戻っフォーム
- に結果を投稿、スレッドは自動的に戻ってみましょうスレッドをプールする必要はありません(スレッドを削除する必要はありません)。
スレッドプールを使用すると、新しいスレッドを作成するコストを節約できます。
あなたはそれらを取り除こうとする悲惨さを救います。
次にあなたがQueueUserWorkItem
を使用して、スレッドプールのスレッド上のオブジェクトのメソッドの手順を実行しますあなたの便利なヘルパーメソッドを持っています。
RunInThreadPoolThread(
GetFileAttributesThreadMethod,
TGetFileAttributesData.Create('D:\temp\foo.xml', Self.Handle),
WT_EXECUTEDEFAULT);
あなたがスレッドのデータ情報を保持するオブジェクトを作成します。
TGetFileAttributesData = class(TObject)
public
Filename: string;
WndParent: HWND;
Attributes: DWORD;
constructor Create(Filename: string; WndParent: HWND);
end;
とし、スレッドコールバックメソッドを作成します。
procedure TForm1.GetFileAttributesThreadMethod(Data: Pointer);
var
fi: TGetFileAttributesData;
begin
fi := TObject(Data) as TGetFileAttributesData;
if fi = nil then
Exit;
fi.attributes := GetFileAttributes(PWideChar(fi.Filename));
PostMessage(fi.WndParent, WM_GetFileAttributesComplete, NativeUInt(Data), 0);
end;
t鶏あなただけのメッセージを処理:
procedure WMGetFileAttributesComplete(var Msg: TMessage); message WM_GetFileAttributesComplete;
procedure TfrmMain.WMGetFileAttributesComplete(var Msg: TMessage);
var
fi: TGetFileAttributesData;
begin
fi := TObject(Pointer(Msg.WParam)) as TGetFileAttributesData;
try
ShowMessage(Format('Attributes of "%s": %.8x', [fi.Filename, fi.attributes]));
finally
fi.Free;
end;
end;
魔法RunInThreadPoolThread
あなたは、スレッド内のインスタンスメソッドを実行することができます綿毛のほんの少しです:
あなたは上のメソッドを呼び出すことができますラッパーだけですインスタンス変数:リーダーため
TThreadMethod = procedure (Data: Pointer) of object;
TThreadPoolCallbackContext = class(TObject)
public
ThreadMethod: TThreadMethod;
Context: Pointer;
end;
function ThreadPoolCallbackFunction(Parameter: Pointer): Integer; stdcall;
var
tpContext: TThreadPoolCallbackContext;
begin
try
tpContext := TObject(Parameter) as TThreadPoolCallbackContext;
except
Result := -1;
Exit;
end;
try
tpContext.ThreadMethod(tpContext.Context);
finally
try
tpContext.Free;
except
end;
end;
Result := 0;
end;
function RunInThreadPoolThread(const ThreadMethod: TThreadMethod; const Data: Pointer; Flags: ULONG): BOOL;
var
tpContext: TThreadPoolCallbackContext;
begin
{
Unless you know differently, the flag you want to use is 0 (WT_EXECUTEDEFAULT).
If your callback might run for a while you can pass the WT_ExecuteLongFunction flag.
Sure, I'm supposed to pass WT_EXECUTELONGFUNCTION if my function takes a long time, but how long is long?
http://blogs.msdn.com/b/oldnewthing/archive/2011/12/09/10245808.aspx
WT_EXECUTEDEFAULT (0):
By default, the callback function is queued to a non-I/O worker thread.
The callback function is queued to a thread that uses I/O completion ports, which means they cannot perform
an alertable wait. Therefore, if I/O completes and generates an APC, the APC might wait indefinitely because
there is no guarantee that the thread will enter an alertable wait state after the callback completes.
WT_EXECUTELONGFUNCTION (0x00000010):
The callback function can perform a long wait. This flag helps the system to decide if it should create a new thread.
WT_EXECUTEINPERSISTENTTHREAD (0x00000080)
The callback function is queued to a thread that never terminates.
It does not guarantee that the same thread is used each time. This flag should be used only for short tasks
or it could affect other timer operations.
This flag must be set if the thread calls functions that use APCs.
For more information, see Asynchronous Procedure Calls.
Note that currently no worker thread is truly persistent, although worker threads do not terminate if there
are any pending I/O requests.
}
tpContext := TThreadPoolCallbackContext.Create;
tpContext.ThreadMethod := ThreadMethod;
tpContext.Context := Data;
Result := QueueUserWorkItem(ThreadPoolCallbackFunction, tpContext, Flags);
end;
エクササイズ:番目に指示GetFileAttributesData
オブジェクト内キャンセルフラグを作成しますeスレッドそのはデータオブジェクトを解放しなければならず、ではなく、は親にメッセージを送信します。
それはあなたが作成していると言って、すべての長い道のりです:
DWORD WINAPI GetFileAttributes(
_In_ LPCTSTR lpFileName,
_Inout_ LPOVERLAPPED lpOverlapped,
_In_ LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
は非同期モデルを除く任意のものを考えるカント。 –
他の状況では、HTTPリクエストを簡単にキャンセル/タイムアウトすることができるため、共有ファイルを提供するためにミニマムウェブサーバーを配備することでこの問題を解決しました。 しかし、この場合、これはさまざまな理由(デプロイメントの問題、セキュリティの問題など)の解決策ではありません。 –