none
IE7の環境、ワーカスレッドから呼び出したCHtmlView::Navigate2がエラーメッセージを表示する RRS feed

  • 質問

  • いつもお世話になっております。nataku06です。

    早速ですが、皆様にご意見頂きたく質問いたします。

    Windows2000、Visual Studio 6.0の環境で作成したアプリケーションが

    IE7のWinodwsXP SP2にてエラーメッセージを出すようになりました。(IE6のWindowsXP SP2環境ではエラーは出ません)

    具体的には、ワーカスレッドからCHtmlView::Navigate2関数を呼び出した際に「'(URL)'が見つかりません。パスまたはインターネットアドレスが正しいかどうかを確認してください。」と表示され、データの取得に失敗します。

    WinInetのInternetOpenUrl関数を使用すると、上のメッセージが表示され、[OK]を押すと正常にデータを取得できました。(以下の現象と同じと思われます。:http://www.gamania.co.jp/ec/news/support_main.asp?id=8722

    また、原因がわからないのですが、ワーカスレッドで呼び出す関数を、スレッドを生成せず、そのまま呼び出した場合はエラーは出ませんでした。

     

    お忙しいところ、大変申し訳ありませんが、

    ワーカスレッドからの呼び出しでエラー画面を出したくないのです。

    何か解決策、お気づきの点や参考情報などございませんでしょうか?よろしくお願いします。

     

    お役に立つかわかりませんが、コードの一部を以下に書きます

    // MainFrame
    CMainFrame::OnStart()
    {
     // スレッド生成
     m_pThread = AfxBeginThread(ThreadFunc,(LPVOID)&ti,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
     m_pThread->m_bAutoDelete = FALSE;
     m_pThread->ResumeThread();
    }

    UINT ThreadFunc(LPVOID pVoid)
    {
     // CMainFrame::GetData呼び出し
     ((CMainFrame*)pThIf->pMainFrame)->GetData(pVoid);
     return 0;
    }

    int CMainFrame::GetData(LPVOID pVoid)
    {
     // CXHtmlView::Navi呼び出し
     m_pHtmlView->Navi(pVoid);
     return 0;
    }

    int CXHtmlView::Navi(LPVOID pVoid)
    {
     // ここでエラーが出る
     Navigate2(((LPTHREADINFO*)pVoid)->pQuery,navNoHistory | navNoReadFromCache | navNoWriteToCache,NULL);
     return 0;
    }

    以上、よろしくお願いします。

    2006年11月20日 5:02

回答

  • 以前はたまたま動作していただけです。

    COM のインターフェースポインタは、スレッド境界を越えると無効になります。

    スレッド境界を跨いでインターフェースポインタを渡す場合は「マーシャリング」するのがお約束です。

    (COM の)マーシャリングそのものや CoMarshalInterface() API 等について調べてみてください。

     

    2006年11月21日 0:37
  • 「ワーカースレッドから呼び出せない」という問題の解決には全くつながらないのですが、どうしてもワーカースレッドから呼び出さなければならないのでしょうか?

    CHtmlView::Navigate2 は非同期操作のように見えますから、呼び出しが完了するまでメインスレッドがブロックされるというような問題は無さそうなのですけれど…。

    ワーカースレッドからトリガーを投げたいということでしたら、適当な Window Message をメインスレッドのメッセージキューに投げるか、イベントを利用することで解決できると思うのです…。

     

    2006年11月24日 10:54

すべての返信

  • 以前はたまたま動作していただけです。

    COM のインターフェースポインタは、スレッド境界を越えると無効になります。

    スレッド境界を跨いでインターフェースポインタを渡す場合は「マーシャリング」するのがお約束です。

    (COM の)マーシャリングそのものや CoMarshalInterface() API 等について調べてみてください。

     

    2006年11月21日 0:37
  • 渋木様、返信ありがとうございます。

    「マーシャリング」についてこれから調べてみます。

    初歩的な質問で申し訳ありませんが

    「CHtmlView::Navigate2」は「COM」を使用しており、

    上記サンプルにおいては、Navigate2の第一引数が、「マーシャリング」されていないから「無効」である

    ということでよろしいのでしょうか?

    2006年11月21日 1:35
  •  nataku06 さんからの引用

    「CHtmlView::Navigate2」は「COM」を使用しており、

    特定のメソッドが「COM を利用している」わけではありません。

    .NET の WebBrowser コントロールは、Internet Explorer の一部である Microsoft WebBrowser コントロールのラッパに過ぎずません。

    そして、Microsoft WebBrowser コントロールは、その全体が COM/OLE/ActiveX 技術を基盤として作られたコントロールなのです。

     nataku06 さんからの引用

    上記サンプルにおいては、Navigate2の第一引数が、「マーシャリング」されていないから「無効」である

    ということでよろしいのでしょうか?

    そのような印象を受けますが、.NET の COM 互換層が何をどこまでやっているかわからないので、精密には分かりません。

    引数の前に、呼び出し自体が失敗することも考えられるのですが、そうはなっていないようですね。

     

     

    2006年11月21日 4:48
  • 「ワーカースレッドから呼び出せない」という問題の解決には全くつながらないのですが、どうしてもワーカースレッドから呼び出さなければならないのでしょうか?

    CHtmlView::Navigate2 は非同期操作のように見えますから、呼び出しが完了するまでメインスレッドがブロックされるというような問題は無さそうなのですけれど…。

    ワーカースレッドからトリガーを投げたいということでしたら、適当な Window Message をメインスレッドのメッセージキューに投げるか、イベントを利用することで解決できると思うのです…。

     

    2006年11月24日 10:54
  • 渋木様、SAKAMOTO様

    返信ありがとうございます。

    現状、マーシャリングに関して調査中ですが

    具体的解決策を思いつきません(勉強不足です。)

    また、ワーカスレッドからの呼び出しの必要性に関しては

    再検討したいと思います。

    2006年11月29日 0:44
  • ワーカスレッドからメインスレッド側に、メッセージを送って(SendMessage)、
    メインスレッド側で、CHtmlView::Navigate2()を行うのが、簡単だと思います。
    2006年11月29日 13:11