如何在CWorkerThread中编写简单的后台线程

2024-04-19

我正在尝试在 Internet Explorer 的附加组件中异步运行函数(我正在用 VC++ 编写 BHO)。按照建议here https://stackoverflow.com/questions/4285346/threading-in-bho-atl-com-winapi-or-something-else/4285377#4285377我正在尝试使用 CWorkerThread。

我花了几个小时试图弄清楚,但仍然不知道该怎么做。我在ATL方面没有太多经验。互联网上缺乏好的文档或教程让我很苦恼。

我通过“添加”->“类”创建类并选择“ATL 简单对象”(这就是将类添加到 ATL 项目的方式,对吗?)。但是这个IWorkerThreadClient怎么实现呢?我认为在类视图中选择“添加”->“实现接口”会很好,但列表中没有 IWorkerThreadClient。

我想我不太了解 ATL 或 COM,但找不到学习这个的好资源(特别是newest ATL7).

我什至尝试过winapiCreateThread方法但它不起作用。我路过this运行静态方法的类指针,但稍后内存会被破坏。尽管如此,如果它有效,我仍然宁愿使用其他东西而不是CreateThread.

现在我有类似的东西this http://msdn.microsoft.com/en-us/library/bb250489%28VS.85%29.aspx. In OnDocumentCompleteRemoveImages(sptmlDoc)我只想异步运行它。

EDIT:我做了什么CreateThread:

我尝试运行RemoveImages函数(来自here https://stackoverflow.com/questions/4285346/threading-in-bho-atl-com-winapi-or-something-else/4285377#4285377) 异步。我在类中创建了静态函数,其签名如下here http://msdn.microsoft.com/en-us/library/ms682516%28v=VS.85%29.aspx。 RemoveImages 有参数,所以我将其复制到类的成员中:

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

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

您尝试在另一个线程中使用在 1 个线程中分配的 COM 句柄,这是一种顽皮行为。 BHO 环境是 STA(单线程公寓),因此您应该编组m_tmpHtmlDocument2在您的线程中使用的对象。

经验表明,在某些情况下,IE 可能会让您摆脱将浏览器 com 对象从一个线程传递到另一个线程,然后获取文档和元素的情况。这是完全不可靠的。

根据 IE 6/7/8,您将有不同的目标线程来执行您的操作,并考虑每个安全级别/框架/选项卡/窗口的级别。基本上任何时候 IE 创建一个新的“站点”

另外,为了防止您的应用程序即使在导航离开页面后仍保持页面活动状态,在 FireFox 中,您将使用nsWeakPointer<>,我从来没有在 IE 中找到过类似的东西。

建议:也许不是因为与页面的交互很慢而将 com 编组到另一个线程,而是尝试改进与页面交互的方式并提高进程性能可能是更好的目标。

以下是使用 CThreadPool 的概述,它将对请求进行排队,然后在池有空间时执行它们。
I use pvWorkerParam将线程绑回站点。
我有不同类型的ActionRequests,您当然可以简化并只为请求传递 null 。
Note:这并不能解决您已经遇到的编组问题

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() );
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在CWorkerThread中编写简单的后台线程 的相关文章

随机推荐