2010-11-28 6 views
2

Ich versuche asynchron Funktion in meinem Add-on für Internet Explorer ausführen (ich schreibe BHO in VC++). Wie vorgeschlagen here Ich versuche CWorkerThread zu verwenden.Wie schreibe ich einfach Hintergrund Thread in CWorkerThread

Ich habe versucht, es stundenlang herauszufinden, aber immer noch keine Ahnung, wie es geht. Ich habe nicht viel Erfahrung in ATL. Das Fehlen von guten Dokumentationen oder Tutorials im Internet bringt mich um.

Ich erstelle Klasse durch Hinzufügen-> Klasse und wählen Sie ATL Simple Object (so fügen Sie als ATL-Projekt klassifiziert hinzu oder?). Aber wie implementiert man diesen IWorkerThreadClient? Ich dachte, dass die Auswahl von Add-> Implement Interface in der Klassenansicht gut ist, aber es gibt keinen IWorkerThreadClient in der Liste.

Ich glaube, ich weiß nicht, ATL oder COM enaugh kann aber nicht gute Ressource finden für das Erlernen dieser (esspessialy neueste ATL7).

Ich versuchte sogar winapi CreateThread Ansatz, aber es funktioniert nicht. Ich übergebe this Klassenzeiger, um statische Methode auszuführen, aber etwas beschädigt später mit Speicher. Wenn es trotzdem funktioniert hätte, würde ich lieber etwas anderes als CreateThread verwenden.

Im Moment habe ich etwas wie this. In OnDocumentComplete gibt es RemoveImages(sptmlDoc) und ich möchte es nur asynchron ausführen.

EDIT: Was ich mit CreateThread tat:

Ich versuchte RemoveImages Funktion (von here) asynchron ausgeführt wird. Ich habe statische Funktion in meiner Klasse mit Signatur wie here erstellt. RemoveImages hat Parameter so kopiert ich es auf ein Mitglied einer Klasse:

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

und MyThreadFunction:

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

    return 0; 
} 

I „Nicht behandelte Ausnahme bei 0x60c0da05 in iexplore.exe erhalten: 0xC0000005: Zugriffsverletzung Leseort 0x000001b8 . " hier in der fett gedruckten Zeile:

 
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

würden Sie Beispiele wie [dieses] einen Blick (http://www.codeproject.com/KB/threads/CWorkerThread .aspx)? –

+0

Ja, tat ich. Ich denke, dass dies und [dies] (http://msdn.microsoft.com/en-us/library/w849dybf.aspx) nur "gute" Quellen über diese Klasse sind. Aber ich habe Probleme damit. Ich kann nicht einmal eine einfache Klasse erstellen, die 'IWorkerThreadClient' implementiert, weil ich "Fehler C2504: 'IWorkerThreadClient': Basisklasse undefiniert" bekomme und ich '#include ' hinzufüge. Ich kann es nur in Objekten implementieren, die von add-> class-> Atl Simple Object erstellt wurden. Ich kann es später nicht benutzen, weil ich keinen Zeiger auf die 'IWorkerThreadClient'-Schnittstelle bekommen kann, um es an 'AddHandle' zu ​​übergeben. –

Antwort

0

und sptmlDoc - ist es ein IHTMLDocumet *?

IWorkerThreadClient - noch nie davon gehört

„Ich selbst winapi Createthread-Ansatz versucht, aber es funktioniert nicht ich diese Klasse Zeiger bin vorbei statische Methode zu laufen, aber etwas mit memomory korrumpiert später.“

Halten Sie es einfach ist das beste Design-Muster von allen. Bleiben Sie also bei CreateThread, es sei denn, Sie haben gute Gründe, dies nicht zu tun. Nun, meine Vermutung ist, dass der Absturz auftritt, weil spptmlDoc zur späteren Verarbeitung an den Thread übergeben wird. Die Sache ist, dass Zeiger vom Ereignis BeforeNavigate bis zum Ereignis DocumentComplete gültig sind. Versuchen Sie, diese Verarbeitung vor Ort (in Ihrem Event-Handler) zu machen und zu sehen, ob es weiterhin abstürzt. Einige Codebuchung würde auch helfen

+0

Es ist am besten, es einfach zu halten, aber "CoInitialize" im Worker-Thread aufzurufen, ist besser. – wqw

+0

IWorkerThreadClient - es ist Zeug für CWorkerThread. Ich aktualisierte meine Frage, die genau beschreibt, was Crushing Hexe 'CreateThread' ist. Kannst du es dir anschauen? –

+0

Erneut würde ich nicht erwarten, dass m_tmpHtmlDocument2 = htmlDoc2 gültig ist, wenn es später in einem Worker-Thread verwendet wird. Überprüfen Sie, ob Sie Ihr Ziel auf demselben Thread erreichen können. Wenn du kannst, dann sehe ich nicht, wie man das Gleiche von einem anderen Thread macht. Und folgen Sie auch dem obigen Ratschlag von wqw – kellogs

2

Ihre Durchführung einer ungezogen, indem Sie versuchen, ein COM-Handle in einem Thread in einem anderen zugeordnet zugewiesen. BHO-Umgebung ist STA (Single Threaded Apartment), also sollten Sie das Objekt m_tmpHtmlDocument2 für die Verwendung in Ihrem Thread bereitstellen.

Experiance hat gezeigt, dass in einigen Fällen IE Sie mit der Übergabe des Browser-com-Objekts von 1 Thread zum anderen durchkommen lassen und dann das Dokument und die Elemente später funktionieren kann. Das ist völlig unzuverlässig.

Je nach IE 6/7/8 haben Sie verschiedene Zielthreads, um Ihre Aktionen auszuführen, indem Sie an die Ebenen pro Sicherheitsstufe/Frame/Tab/Fenster denken. im Grunde jederzeit IE einen neuen ‚Standort‘ erstellt

auch Ihre App von Halten der Seiten aktiv, auch nach der Navigation zu verhindern weg von der Seite, in FireFox würden Sie ein nsWeakPointer<> verwenden, ich habe nie die equivelant im Internet Explorer.

Vorschlag: Vielleicht ist es besser, statt com zu einem anderen Thread zu migrieren, da Ihre Interaktion mit der Seite langsam ist. Sie sollten versuchen, die Interaktion mit der Seite zu verbessern und die Leistung im Prozess zu verbessern.

Hier ist eine Gliederung mit dem CThreadPool, die Anforderungen in Warteschlange stellen und dann ausführen, wenn der Pool Platz hat.
Ich verwende pvWorkerParam, um die Threads zurück an die Site zu binden.
Ich habe verschiedene Arten von ActionRequests, Sie könnten natürlich vereinfachen und einfach Null für die Anfrage übergeben.
Hinweis: Dies löst nicht Probleme Rangier haben Sie bereits

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()); 
    } 
}