問題タブ [tmonitor]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
delphi - TMonitor.Destroy の無効なポインタ操作
現在、既存の Delphi 5 アプリケーションを Delphi 2010 に移植する作業を行っています。
これは、Outlook に読み込まれるマルチスレッド DLL (Outlook によってスレッドが生成される場所) です。Delphi 2010 でコンパイルすると、フォームを閉じるたびに、TMonitor.Destroy 内で「無効なポインタ操作」が発生します... system.pas にあるものです。
これは既存のやや複雑なアプリケーションであるため、調査すべき多くの方向性があり、デルファイのヘルプには、この特定の TMonitor クラスを最初にほとんどドキュメント化していません(追加情報を含むいくつかの Allen Bauer の投稿にたどり着きました)。 ) ... そこで、まず、誰かが以前にこれに遭遇したかどうか、またはこの問題の原因について何か提案があるかどうかを尋ねてみようと思いました。記録のために: 私は自分のコードで明示的に TMonitor 機能を使用していません。ここでは、Delphi 5 コードのストレート ポートについて話しています。
問題が発生した時点でコールスタックを編集します。
delphi - Delphi System ユニットの TMonitor は何に適していますか?
「The Oracle at Delphi」(Allen Bauer)の記事「Simmering Unicode、DPL を沸騰させる」および「Simmering Unicode、DPL を沸騰させる (パート 2)」を読んだ後、Oracle は私が理解するすべてです:)
この記事では、Delphi Parallel Library (DPL)、ロック フリー データ構造、相互排他ロック、および条件変数について言及しています(このウィキペディアの記事では、「モニター (同期) 」に進み、スレッド同期用の新しいTMonitor レコード タイプを紹介し、そのいくつかについて説明します。メソッド。
この Delphi レコード タイプをいつ、どのように使用できるかを示す例を含む紹介記事はありますか? オンラインでいくつかのドキュメントがあります。
TCriticalSection と TMonitor の主な違いは何ですか?
Pulse
メソッドとメソッドを使用して何ができPulseAll
ますか?たとえば、C# や Java 言語に対応するものはありますか?
RTL または VCL にこの型を使用するコードはありますか (例として役立つ可能性があります)。
更新: Delphi 2009 で TObject のサイズが 2 倍になった理由の記事 Delphi のすべてのオブジェクトは、TMonitor レコードを使用してロックできるようになったと説明していますが、インスタンスごとに 4 バイトの追加料金がかかります。
TMonitor は、Java 言語の Intrinsic Locksと同様に実装されているようです。
すべてのオブジェクトには固有のロックが関連付けられています。慣例により、オブジェクトのフィールドへの排他的かつ一貫したアクセスを必要とするスレッドは、オブジェクトにアクセスする前にオブジェクトの固有ロックを取得し、それらの操作が完了したら固有ロックを解放する必要があります。
Delphi のWait、Pulse、およびPulseAllは、Java プログラミング言語の wait() 、 notify() 、および notifyAll() に相当するようです。間違っていたら訂正してください:)
更新 2: Java(tm) チュートリアルの保護されたメソッドに関する記事に基づいて、 と を使用するProducer/Consumer アプリケーションのサンプル コード(コメントを歓迎します):TMonitor.Wait
TMonitor.PulseAll
この種のアプリケーションは、データを作成するプロデューサとデータを処理するコンシューマの 2 つのスレッド間でデータを共有します。2 つのスレッドは、共有オブジェクトを使用して通信します。調整は不可欠です。コンシューマー スレッドは、プロデューサー スレッドがデータを配信する前にデータの取得を試みてはならず、コンシューマーが古いデータを取得していない場合、プロデューサー スレッドは新しいデータの配信を試みてはなりません。
この例では、データは一連のテキスト メッセージであり、Drop タイプのオブジェクトを通じて共有されます。
現在、これは期待どおりに機能しますが、改善できる詳細がありTMonitor.Enter(Self);
ます。Drop インスタンス全体を でロックする代わりに、(プライベート) "FLock" フィールドを使用して、 Put および Take メソッド by TMonitor.Enter(FLock);
.
InterruptedException
コードを Java バージョンと比較すると、Delphi には の呼び出しをキャンセルするために使用できるものがないことにも気付きSleep
ます。
更新 3 : 2011 年 5 月に、OmniThreadLibrary に関するブログ エントリで、TMonitor 実装のバグの可能性が示されました。Quality Centralのエントリに関連しているようです。コメントには、パッチが Delphi ユーザーによって提供されたことが記載されていますが、表示されません。
更新 4 : 2013 年のブログ投稿では、TMonitor は「公正」ですが、そのパフォーマンスはクリティカル セクションのパフォーマンスよりも悪いことが示されました。
delphi - TMonitor.Pulse と TMonitor.PulseAll の比較
Delphi Docwiki では、呼び出しスレッドがオブジェクトを解放するとすぐに、指定されたオブジェクトをロックできるようになることを、Pulseが待機キュー内の次のスレッドに通知すると説明しています。PulseAllは、待機キュー内のすべてのスレッドにシグナルを送ります。
スレッド化されたキューの実装で Pulse を使用するこのコードを見つけました。上記の定義を考えると、PulseAll を使用するか、別の方法で質問する必要があると思います。PulseAll の代わりに Pulse を使用するのはいつですか? (基本的な質問は次のとおりです。「キュー内の次のスレッド」が常に通知する必要があるスレッドであることをどのように確認できますか。ただし、スレッドが合計で 2 つしかない場合や、コードが安全に実行できる場合を除きます。唯一の待機中のスレッドは、通知/「パルス」が必要なスレッドであると仮定します)?
Java 言語の対応する同期メソッドについて、次の質問を見つけました: Java: notify() vs. notifyAll() all over again
更新: 上記の Java の質問には興味深い回答が 1 つあります。これは、put と get の 2 つのメソッドしかなく、notify() (Pulse() の Java 版) を使用するプロデューサー/コンシューマー アプリケーションでもデッドロックが発生する可能性があることを示しています。 : Java: notify() 対 notifyAll() の繰り返し
回答には推奨事項が含まれています
どちらを使用すればよいかわからない場合は、 を使用して
notifyAll
ください。
multithreading - Delphiでは、System.TMonitor.PulseとTMonitor.PulseAllは実際に何をしますか
DelphiがDelphi2009でTMonitorレコードを導入し、マルチスレッド環境で特定のオブジェクトをロックできるようになったことを非常に嬉しく思います。私を困惑させたのは、このレコードタイプのPulseメソッドとPulseAllメソッドです。
たとえば、DelphiのヘルプのPulseのエントリには、「待機キュー内の次のスレッドに、呼び出し元のスレッドがオブジェクトを解放するとすぐに、指定されたオブジェクトをロックできるようになることを通知します」と記載されています。
本当に?どういう意味ですか?私は問題なくPulseを使用せずにTMonitorを使用しました。さらに、DelphiのソースでのTMonitorの使用の一部は、Pulseを使用しません。
PulseメソッドとPulseAllメソッドは、.NET Monitorクラスとのソースレベルの互換性のためにDelphiのTMonitorレコードにのみ含まれていますか、それとも本当に目的を果たしていますか?
この問題を説明する2つの質問(「TMonitor.PulseとTMonitor.PulseAll」および「DelphiシステムユニットのTMonitorは何に適しているか」)がありますが、私は決定的な答えを探しています。
delphi - Delphi 2009 で TMonitor はどのように「壊れた」のですか?
インターネット上には、Delphi 2009 で TMonitor 同期クラスの実装がひどく壊れているというバグ レポートがいくつかあります。
ただし、次のような修正 (パッチ) を示すページも見つけました: TMonitor バグ? - http://www.thedelphigeek.com/2011/05/tmonitor-bug.html
パッチは TMonitor を修正するのに十分ですか、それとも他に重大な問題がありますか?
delphi - 列挙子のコンストラクタ/デストラクタ内でロック (TMonitor) を使用しても安全ですか?
シンプルなスレッドセーフなコンテナ クラスがあります。標準の追加/削除メソッドがあります。通常、アイテムの列挙は次のように実装されます。
しかし、スレッドセーフな方法で for-in サポートを利用したい:
私の列挙子の実装は、コンテナーをコンストラクターでロックし、デストラクターでロックを解除します。これは機能しますが、列挙子のインスタンスが for-in ループの最初に作成され、最後に破棄されるという前提に基づいています。ここでその説明を見つけました: How is Enumerator created with for in construction destroy?
でも施錠・解錠は大事な操作なので、こういう使い方でいいのかな?
これが私の実装です: