2010-11-28 7 views
2

私はInternet Explorerのアドオンで非同期に関数を実行しようとしています(私はVC++でBHOを書いています)。提案通り、here私はCWorkerThreadを使用しようとしています。CWorkerThreadで簡単なバックグラウンドスレッドを書くには

私は何時間もそれを理解しようとしてきましたが、それをどうやって行うのかまだ分かりません。私はATLで多くの経験がありません。インターネット上の良い文書やチュートリアルの欠如は私を殺している。

私はAdd-> Classでクラスを作成していて、ATL Simple Objectを選択しています(ATLプロジェクトにクラスを追加する方法は?)。しかし、このIWorkerThreadClientを実装する方法は?私はクラスビューでAdd-> Implement Interfaceを選択すると良いと思ったが、リストにはIWorkerThreadClientはないと思った。

私はATLまたはCOM enaughについてはわかりませんが、これを学ぶための優れたリソースを見つけることはできないと思います(詳細最新 ATL7)。

私もwinapi CreateThreadアプローチを試みましたが、それは動作していません。私はthis静的メソッドを実行するクラスポインタを渡していますが、後で何かがメモリで破損しています。それでも働いていたら、私はまだCreateThread以外の何かを使用したいと思っています。

今私はthisのようなものを持っています。 OnDocumentCompleteにはRemoveImages(sptmlDoc)があり、私はそれを非同期に実行したいだけです。

編集:私はCreateThreadでやった

私は非同期的に(hereから)RemoveImages機能を実行してみました。私はhereのような署名で私のクラスの静的関数を作成しました。 RemoveImagesは、私はクラスのメンバにコピーし、次のパラメータがあります。

if (htmlDoc2 != NULL) 
{ 
    m_tmpHtmlDocument2 = htmlDoc2; 
    m_hThread = CreateThread(NULL, 0, MyThreadFunction, this, 0, &m_threadId); 
} 

MyThreadFunction

static DWORD WINAPI MyThreadFunction(LPVOID lpParam) 
{ 
    CHelloWorldBHO* myClass = (CHelloWorldBHO*)lpParam; 
    myClass->RemoveImages(myClass->m_tmpHtmlDocument2); 

    return 0; 
} 

私はiexplore.exeをして0x60c0da05で」未処理の例外を取得:0xc0000005で:アクセス違反読み取り場所0x000001b8 "ここでは太字で示しています。

 
void CHelloWorldBHO::DontDisplayElement(CComPtr htmlElement) 
{ 
    CComPtr style; 
    HRESULT hr = htmlElement->get_style(&style); 

    if (hr == S_OK && style != NULL) 
    {  
     static const CComBSTR strNone(L"none"); 
     style->put_display(strNone); 
    } 
} 
+0

あなたは[この1](http://www.codeproject.com/KB/threads/CWorkerThreadのような例を見てみたのを持って整列化の問題が解決しません.aspx)? –

+0

はい、私はしました。私はこれと[this](http://msdn.microsoft.com/en-us/library/w849dybf.aspx)はこのクラスに関する "良い"ソースだと思います。 しかし、私はこれに問題があります。私は "エラーC2504: 'IWorkerThreadClient':基本クラスが定義されていないので、' IWorkerThreadClient'を実装する単純なクラスを作成することすらできず、 '#include 'を追加しています。私はadd-> class-> Atl単純オブジェクトによって作成されたオブジェクトにしか実装できません。なぜ私は 'IWorkerThreadClient'インターフェースへのポインタを' AddHandle'に渡すことができないのか、後でそれを使うことはできません。 –

答えて

0

とsptmlDoc - これはIHTMLDocumet *ですか?

IWorkerThreadClient -

「私もWINAPIののCreateThreadのアプローチを試みたが、私は、静的メソッドを実行するには、このクラスのポインタを渡している動作していないが、何かが後でmemomoryで破壊されている」

それを聞いたことがありません

シンプルに保つことは、それらのデザインパターンのすべてがベストです。だからあなたが良い理由がない限り、CreateThreadに固執してください。さて、私の推測では、sptmlDocが後で処理するためにスレッドに渡されるためにクラッシュが発生するということです。そのようなポインタはBeforeNavigateイベントからDocumentCompleteイベントまで有効です。イベントハンドラの内部でその処理を行い、クラッシュが発生していないかどうかを確認してください。いくつかのコード投稿も役に立ちます

+0

シンプルにするのが一番ですが、ワーカースレッドで 'CoInitialize'を呼び出す方が良いです。 – wqw

+0

IWorkerThreadClient - CWorkerThreadのためのものです。 魔法の 'CreateThread'を壊しているものを正確に記述して私の質問を更新しました。あなたはそれを見てみることができますか? –

+0

再び、私はm_tmpHtmlDocument2 = htmlDoc2が後であるワーカースレッドで使用されたときに有効であるとは思わないでしょう。最初に同じスレッドで目標を達成できることを確認してください。可能であれば、私は他のスレッドから同じことをする方法を見ていません。また、上記のwqwのアドバイスに従ってください – kellogs

2

あなたは1つのスレッドに割り当てられたCOMハンドルを別のスレッドに割り当てようとしています。 BHO環境はSTA(Single Threaded Apartment)なので、m_tmpHtmlDocument2オブジェクトをスレッドで使用するためにマーシャリングする必要があります。

Experianは、ブラウザのCOMオブジェクトを1つのスレッドから別のスレッドに渡してから、ドキュメントと要素を取得してしまう可能性がある場合があることを示しています。これは完全に信頼できません。

IE 6/7/8に応じて、セキュリティレベル/フレーム/タブ/ウィンドウのレベルで考えて、アクションを実行するターゲットスレッドが異なります。基本的にはいつでもIEは新しい「サイト」を作成します

また、ページからのナビゲーションの後でもページをアクティブにしないようにするには、FireFoxでを使用します。IEで等価物を見つけたことはありません。

提案:おそらく、ページとのやりとりが遅いためにcomを別のスレッドにマーシャリングするのではなく、ページの操作方法を改善してプロセスのパフォーマンスを向上させる方が良いでしょう。

ここでは、要求をキューに入れ、プールにスペースがあるときに実行するCThreadPoolを使用したアウトラインを示します。
pvWorkerParamを使用してスレッドをサイトに戻します。
私は異なる種類のActionRequestsを持っていますが、もちろん単純化してリクエストにnullを渡すこともできます。
注:これは、あなたがすでに

class ActionRequest{ 
    DontDisplayElement();// define your do stuff in here 
}; 

class ScriptWorker 
{ 
public: 
ScriptWorker(void); 
virtual ~ScriptWorker(void); 

public: 
BOOL Initialize(void* pvWorkerParam); 
void Execute(ActionRequest *request, void* pvWorkerParam, OVERLAPPED* pOverlapped){ 
try{ 
     std::auto_ptr<ActionRequest> cleanupRequest(request); 
     request.DontDisplayElement(); 
    } catch(...) {} 
    } 
void Terminate(void* pvWorkerParam); 

private: 
boolean m_bCoUninit; 
}; 

Site{ 
    CThreadPool<ScriptWorker> m_scriptWorkerThread; 
    Site() { 
    void *pvWorkerParam = this;// or whatever you want to have passed to every script worker and execute in the pool. 
    m_scriptWorkerThread.Initialize(pvWorkerParam, 1); 
    } 
    OnDocumentComplete() { 
    m_scriptWorkerThread.QueueRequest(new ActionRequest()); 
    } 
} 
関連する問題