1

Delphiでスレッドを開始し、そのために次のコードを使用する必要があります。

function ThreadFunc(tp: PThreadParams): Integer;
var
    I: Integer;
begin
    OutputDebugString(PChar('ThreadFunc, 1'));
    for I := 0 to 10000 do
    begin
        if (I MOD 100) = 0 then
        begin
                OutputDebugString(PChar('Sample Delphi DLL ' + IntToStr(I)));
        end;

    end;

    Dispose(tp);
end;

procedure RunThread;
var
tp : PThreadParams;
Thread : THandle;
ThreadID : Cardinal;
ExitCode : Cardinal;
begin
    New(tp);

    OutputDebugString(PChar('RunThread, 1'));

    Thread := BeginThread(nil, 0, @ThreadFunc, tp, 0, ThreadID);

    OutputDebugString(PChar('RunThread, 2. ThreadID: ' + IntToStr(ThreadID)));

    WaitForSingleObject(Thread, INFINITE);

    GetExitCodeThread(Thread, ExitCode);

    CloseHandle(Thread);
end;

RunThreadを実行すると、ログファイルにエントリが含まれます

RunThread、1

RunThread、2。ThreadID:..。

ただし、からのログ出力はありませんThreadFunc

ThreadFunc実際のスレッド関数( )を実行するには、このコードをどのように変更すればよいですか?

4

2 に答える 2

5

TThreadを使ってみませんか?スレッドの実装が非常に簡単になります。;-)

于 2012-09-18T11:59:14.387 に答える
0

OutputDebugStringについて

あなたの場合の問題は、おそらくOutputDebugStringと、DelphiIDEがそれを処理する方法にあります。スレッドに問題はありません。正常に動作します。それの唯一の欠点は、ThreadFuncが値を返さなければならないことですが、あなたの場合はそうではありません。https://msdn.microsoft.com/en-us/library/windows/desktop/ms686736(v=vs.85).aspxを参照してください (ゼロを返すだけです。最も単純なケースです)。

DelphiがOutputDebugStringを適切に処理するかどうかを確認するには、別のアプリケーションを使用してデバッグメッセージを表示します。

Delphiを終了し、 https: //technet.microsoft.com/en-us/sysinternals/debugview.aspxでWindows SysinternalsからDebugViewを取得して実行し、実行中にアプリケーションも実行します(Delphiが実行されていないことを確認してください)。ランニング)。

DebugViewログには、次のようなものが表示されます。

[8484] RunThread, 1
[8484] RunThread, 2. ThreadID: 8388
[8484] ThreadFunc, 1
[8484] Sample Delphi DLL 0
[8484] Sample Delphi DLL 100
[8484] Sample Delphi DLL 200
<<< 96 lines skipped >>>
[8484] Sample Delphi DLL 9900
[8484] Sample Delphi DLL 10000

OutputDebugStringはあいまいすぎて、信頼できません。ファイルを作成したり、ビープ音を鳴らしたりするなど、スレッドが実行されていることを確認するための単純な方法。したがって、DebugViewが役に立たない場合は、スレッドからOutputDebugStringを出力し、他のメソッドを使用するだけで、スレッドが実行されていることを確認できます。たとえば、次の文字列をThreadFuncの先頭に追加します。

MessageBox(0, 'Thread Text', 'Thread Caption', MB_OK);

アプリケーションを実行します。メッセージダイアログが表示されれば、スレッドは正常に実行されています。

呼び出し規約について

ここでは、呼び出し規約(stdcallとregister)は問題ではありません。その意味であなたのコードは正しいです。System.pasでBeginThread関数の実装を探します(TThreadFuncが存在する場合は、その定義を探します)。

Delphiのどのバージョンを使用したか、または他の互換性のあるコンパイラを使用している可能性については言及していません。これはタイプに影響を与えた可能性がありますが、この可能性は非常に低いです。Delphi 10.2は、ThreadWrapper関数を使用してWindows API CreateThread()に渡します。このThreadWrapperは、実行されるCreateThread()に直接渡されるため、Win32仕様で要求される「stdcall」呼び出し規約で定義されています。次に、ThreadWrapperは、レジスタ呼び出し規約を持つTThreadFuncを呼び出します。TThreadFuncは、次のように定義されます(単純で単純)。

TThreadFunc = function(Parameter: Pointer): Integer;

したがって、上記のコードが示しているように、ThreadFuncはTThreadFuncの宣言と正確に一致する必要があります。コメントで言うように、「stdcall」である必要はありません。ご使用のバージョンのDelphiのSystem.pasにTThreadFuncがない場合は、BeginThreadの3番目のパラメーターに必要なタイプを探して、すべてが正しいことを確認してください。

コンパイラオプション「Typed@operator」をオン(デフォルトではオフ)にしていて、呼び出し規約の不一致に問題がある場合、コンパイラはエラーを出していました。「Typed@operator」オプションを常にオンにすることをお勧めします。または、CreateThread呼び出しの前に(またはファイルの先頭に){$T+}を追加します。したがって、不一致がないことを確認します。

私が説明したように、ここでは呼び出し規約は問題ではなく、コード内のすべてが正しいことが示されています。呼び出し規約が不適切だった場合、終了するまでパラメーターは必要ないため(Dispose(tp))、ThreadFuncは最後まで実行されていたため、すべてのOutputDebugString呼び出しを実行した後にアクセス違反エラーが発生していました。 – Dispose(tp)またはThreadFuncの終了時。デバッガーで出力が表示され、その後アクセス違反が発生します。アクセス違反がなかったので-呼び出し規約ですべてがOKです。

于 2017-05-10T15:45:00.653 に答える