Thanks a lot Xavier ! That article helped a lot. I could make my UI
completely responsive while the XPCOM processed long running tasks in
a background thread.
For the second question, the PRThreadState needs to be set to
STATE_UNJOINABLE if you wish to have the main thread return control
after starting the worker thread.
So for reference here are some code snippets if you wish to perform
long running tasks in a background thread that sends progress
notifications to the UI thread.
// MyComp.cpp
// Code to start the worker thread
// Create a class that implements the nsIRunnable interface
// pass a pointer to my MyComp's Interface so that the worker thread
can invoke a
// notification method on it.
NS_IMETHODIMP MyComp::StartLongTask(....)
....
nsCOMPtr<IMyComp> myIComp = do_QueryInterface(this);
MyRunnable* myRunnable = new MyRunnable(myIComp);
nsCOMPtr<nsIRunnable> my_nsIRunnable = do_QueryInterface(myRunnable);
// create the worker thread:
nsCOMPtr<nsIThread> workerThread =
do_CreateInstance("@mozilla.org/thread;1");
workerThread->Init(my_nsIRunnable,
(PRUint32)0,
(PRThreadPriority)nsIThread::PRIORITY_NORMAL,
(PRThreadScope)nsIThread::SCOPE_GLOBAL,
(PRThreadState)nsIThread::STATE_UNJOINABLE);
workerThread->Join();
....
// notifyObserver method that will broadcast the registered topic to
all listeners
// This method must be a method defined in the IDL of IMyComp
NS_IMETHODIMP MyComp::NotifyObservers(const char *topic, const char
*data) {
PRUnichar* pruData = NULL;
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1");
if (data != NULL) {
// convert const char* to PRUnichar*
pruData = ....
}
observerService->NotifyObservers (NULL, topic, pruData);
return NS_OK;
}
// MyRunnable.cpp
NS_IMETHODIMP InstallProcessor::Run() {
// do something
notifyObservers(topic, data);
// do more things
notifyObservers(topic, data);
}
void MyRunnable::notifyObservers(const char* topic, const char* data) {
nsresult rv = NS_OK;
nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
do_GetService("@mozilla.org/xpcomproxy;1");
nsCOMPtr<IMyComp> proxyMyComp;
rv = pIProxyObjectManager->GetProxyForObject( NS_UI_THREAD_EVENTQ,
IMyComp::GetIID(),
_myComp, // the
MyComp pointer passed to constructor
PROXY_SYNC |
PROXY_ALWAYS,
getter_AddRefs(proxyMyComp));
if (proxyMyComp) {
proxyMyComp->NotifyObservers(topic, data);
}
}
Finally in the JS
// implement the observer interface. This is very easy in JS
var myObserver = { observe : function(subject, topic, data) {
if (topic == "myTopic") {
// update UI with progress
info
}
}
};
// register the observer
var observerService =
Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
observerService.addObserver(myObserver, "myTopic", false);
// start the long running task
myComp.startLongTask(...);
-Sandip
BRUYET Xavier wrote:
> > Question1: How do I get the Main thread from the worker thread ?
>
> I asked the same question one month ago. The response (not easy to
> find) is here :
> http://www.mozilla.org/projects/xpcom/Proxies.html
>
> If you want to call a method which performs graphical works but you are
> not in the graphical thread, you have to create a proxy from your
> object and call the method on this proxy instead of your object.
>
> Xavier.
_______________________________________________
dev-tech-xpcom mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-xpcom