2010-11-28 4 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과 같은 서명으로 정적 함수를 만들었습니다. 내가 iexplore.exe를에 0x60c0da05에서 "처리되지 않은 예외가

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

    return 0; 
} 

:

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

MyThreadFunction : RemoveImages이 매개 변수 그래서이 클래스의 멤버에 복사했다가 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

당신이 [이 사람] (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 Simple Object에 의해 생성 된 객체에서만 그것을 구현할 수있다. 나는'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

한 스레드에서 할당 된 COM 핸들을 다른 스레드에 할당하여 사용하는 것이 좋지 않습니다. BHO 환경은 STA (Single Threaded Apartment)이므로 스레드에서 사용하기 위해 m_tmpHtmlDocument2 객체를 정렬해야합니다.

Experian은 어떤 경우 IE를 사용하면 브라우저 COM 객체를 1 스레드에서 다른 스레드로 전달한 다음 나중에 문서와 요소를 가져 오는 것이 효과적 일 수 있음을 보여주었습니다. 이것은 전적으로 신뢰할 수 없습니다.

IE 6/7/8에 따라 보안 수준/프레임/탭/창 수준에서 생각한 작업을 수행 할 대상 스레드가 달라집니다. 기본적으로 언제든지 IE는 새로운 '사이트'를 생성합니다.

또한 페이지에서 탐색 한 후에도 페이지를 활성 상태로 유지하지 못하게하려면 FireFox에서 nsWeakPointer<>을 사용합니다. 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()); 
    } 
} 
관련 문제