8

非常にマルチスレッド化されているアプリケーションで多数のクラッシュに直面しています。

これらのMSDNページテクニカルノート、およびTLSに関するこの記事を読んでCWnd、オブジェクトがスレッドローカルストーガ(スレッド依存のメモリアクセスであるTLS)のHWNDにマップされていることを理解しました。

HWNDCWndスレッドリモートアクセスのように見えるものをすべて分離し、それを参照に変換して::PostMessage、通信ポートとして使用するつもりでした。

しかし、私の同僚の1人は、私が外国人のスレッドにとどまり、ポリシーCWnd*を採用しても大丈夫だと本当に主張しましたが、ネイティブを回復するために外国人のスレッドでまたはを使用します。::PostMessageCWnd::GetSafeHwnd()pMyCWnd->m_hWndHWND

私は、がスレッドセーフであることをどこにも見たことがなく、オブジェクトがTLSにあるため、別のスレッドでの値が異なると主張してきました。GetSafeHwnd()CWnd

私は間違っていますか?MSDNは明らかに予期しない結果という用語を使用しています。

作成者スレッドからの呼び出しCWnd::GetSafehwnd()または外部スレッドについて、あなたの見解は何ですか?pMyCWnd->m_hWnd

これが安全かどうかを示すMSDNドキュメントはありますか。

4

3 に答える 3

10

CWndはHWNDにマップされません。HWNDはCWndにマップされ、これはスレッドごとに発生します。CWndオブジェクトはTLSにはありませんが(どのように機能しますか?)、一時的なCWndオブジェクトはスレッドごとに作成されます。

間違ったスレッドから一時的なCWndオブジェクトにアクセスすることは、間違いなく悪い考えです(Mark Ransomによって説明されている理由のため)。

ただし、永続的なCWndオブジェクト(たとえば、アプリのメインウィンドウを表す)がある場合は、一度作成すると、どのスレッドからでもm_hWndメンバーにアクセスしてもまったく問題はありません。これは、メモリ内の値であり、変更されることはありません。

これで問題が発生した場合(明示的に文書化されていないため)、HWNDのコピーを作成し、スレッドにアクセスさせます。

PSこれはあなたが英語でリンクした記事です。

于 2012-02-17T17:18:46.927 に答える
5

thisGetSafeHwndは、がNULLかどうかをチェックし、そうでない場合はNULLを返し、そうでない場合はNULLを返す単なるラッパーm_hWndです。それ自体よりもスレッドセーフになることはありませんm_hWnd

一時的なCWnd*を作成すると、MFCは、メッセージループの次のパスなど、安全であると見なした時点でCWnd*を破棄します。MFCを使用しているスレッドが複数ある場合、一時オブジェクトを使用している間に一時オブジェクトが破壊される可能性があります。スレッドから実行できることは、このエラーを検出しません。

于 2012-02-17T16:57:53.310 に答える
1

複数のスレッドがすべて一度にHWNDにアクセスしようとしているマルチスレッドアプリケーションがある場合、設計上の問題があるように思われます。スレッドを計算に制限し、メインスレッドのUIの問題を処理することはできませんか?これは、優れたマルチスレッドアプリの典型的な設計です。

于 2012-02-17T16:49:35.040 に答える