I have reworked a lot of code, removing a lot of extra cruft and have 
(for the time being) gotten Windows to not crash when I try to start a 
background thread.  This code is run when starting an app and will 
happily add to the <listbox id="thread_dump"> forever in OS X but will 
only run for about 11 seconds on Windows.

This is run on startup:

var async = Cc['@flickr.com/async;1'].createInstance(Ci.IAsync);
async.start(callback);

The callback code is in the same file as the rest of the UI stuff:

var callback = {
        add: function(id, result) {
                var lb = document.getElementById('thread_dump');
                var item = lb.appendItem('id: ' + id + ', result: ' + result);
                lb.ensureElementIsVisible(item);
        },
        QueryInterface: function(iid) {
                if(!iid.equals(Ci.nsISupports) &&
                   !iid.equals(Ci.ICallback))
                        throw Components.results.NS_ERROR_NO_INTERFACE;
                return this;
        },
        getInterfaces: function(count) {
                var ifaces = [
                        Ci.nsISupports,
                        Ci.ICallback,
                        Ci.nsIClassInfo
                ];
                count.value = ifaces.length;
                return ifaces;
        },
        getHelperForLanguage: function(language) {
                return null;
        },
        contractID: null,
        classDescription: 'callback',
        classID: null,
        implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
        flags: 0
};

The ICallback and IAsync interfaces:

#include "nsISupports.idl"
[scriptable, uuid(31ec9ecc-3ace-11dc-8314-0800200c9a66)]
interface ICallback : nsISupports
{
        void add(in long id, in AString result);
};


#include "nsISupports.idl"
interface ICallback;
[scriptable, uuid(46732fb4-3a31-11dc-8314-0800200c9a66)]
interface IAsync : nsISupports
{
        void start(in ICallback callback);
        void add(in long id, in long thumbSize, in AString path);
};

This code is in the app's components/ directory and implements the 
IAsync interface:

const CLASSNAME = 'async';
const CONTRACTID = "@flickr.com/async;1";
const CID = Components.ID('{46732fb4-3a31-11dc-8314-0800200c9a66}');
const Cc = Components.classes;
const Ci = Components.interfaces;
var async = function() {
};
async.prototype = {
        add: function(id, thumbSize, path) {
        },
        start: function(callback) {
                var pom = 
Cc['@mozilla.org/xpcomproxy;1'].getService(Ci.nsIProxyObjectManager);
                var eqs = 
Cc['@mozilla.org/event-queue-service;1'].getService(Ci.nsIEventQueueService);
                var callback = 
pom.getProxyForObject(eqs.getSpecialEventQueue(Ci.UI_THREAD_EVENT_QUEUE),
                        Ci.ICallback, callback, 
Ci.nsIProxyObjectManager.INVOKE_ASYNC);
                var thread = 
Cc['@mozilla.org/thread;1'].createInstance(Ci.nsIThread);
                thread.init(new background(callback), 0, 
Ci.nsIThread.PRIORITY_NORMAL,
                        Ci.nsIThread.SCOPE_GLOBAL, Ci.nsIThread.STATE_JOINABLE);
        },

        QueryInterface: function(iid) {
                if(!iid.equals(Ci.nsISupports) &&
                   !iid.equals(Ci.async))
                        throw Components.results.NS_ERROR_NO_INTERFACE;
                return this;
        },
        getInterfaces: function(count) {
                var ifaces = [
                        Ci.nsISupports,
                        Ci.async,
                        Ci.nsIClassInfo
                ];
                count.value = ifaces.length;
                return ifaces;
        },
        getHelperForLanguage: function(language) {
                return null;
        },
        contractID: null,
        classDescription: 'async',
        classID: null,
        implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
        flags: 0
};

var background = function(callback) {
        this.callback = callback;
};
background.prototype = {
        run: function() {
                var thread = 
Cc['@mozilla.org/thread;1'].createInstance(Ci.nsIThread).currentThread;
                var i = 0;
                while (true) {
                        this.callback.add(i++, 'foo');
                        thread.sleep(1000);
                }
        }
};
var Module = new Object();
Module.registerSelf = function(compMgr, fileSpec, location, type) {
        compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(CID, CLASSNAME, CONTRACTID, fileSpec, 
location, type);
}
Module.getClassObject = function(compMgr, cid, iid) {
        if(!cid.equals(CID)) throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
        if(!iid.equals(Ci.nsIFactory)) throw 
Components.results.NS_ERROR_NO_INTERFACE;
        return Factory;
}
Module.canUnload = function(compMgr) {
        return true;
}
var Factory = {};
Factory.createInstance = function(outer, iid) {
        if(outer != null) throw Components.results.NS_ERROR_NO_AGGREGATION;
        return new async();
}
function NSGetModule(compMgr, fileSpec) {
        return Module;
}


This is again rather similar to Steve's example at 
http://skrul.com/blog/projects/threaddemo but takes much of the 
complexity out in the name of getting something working.

In Windows XULRunner 1.8.1.3 this will run, adding 11 items to the 
listbox before the background thread goes dead.  The UI remains 
responsive throughout.  In OS X this will run indefinitely, again with 
the UI remaining responsive throughout.

I can't find any documented similar situations.  Is there some condition 
I am tripping that makes the thread die?

Thanks,

Richard
[EMAIL PROTECTED]
_______________________________________________
dev-tech-xpcom mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-xpcom

Reply via email to