c# - InvalidComObjectException when using GeckoWebBrowser -
i using geckowebbrowser geckofx45 extract source of webpage after loaded.
when running code once works fine, when run multiple times invalidcomobjectexception
is thrown:
system.runtime.interopservices.invalidcomobjectexception: 'com object has been separated underlying rcw cannot used.'
code:
public static async task<string> loaddomsourceasync(string url, cancellationtoken cancellationtoken) { using (var apartment = new messageloopapartment()) return await apartment.run(async () => { using (var wb = new geckowebbrowser()) { var tcs = new taskcompletionsource<string>(); try { wb.documentcompleted += (s, a) => tcs.trysetresult(((geckohtmlhtmlelement)wb.document.documentelement).outerhtml); wb.navigationerror += (s, a) => tcs.trysetexception(new geckonetworkexception()); wb.navigate(url); return await tcs.task; } catch (exception e) { tcs.trysetexception(e); } { wb.stop(); } return null; } }, cancellationtoken); }
messageloopapartment:
using system; using system.linq; using system.threading; using system.threading.tasks; using system.windows.forms; namespace streamlinkextract { /// <summary> /// messageloopapartment /// sta thread message pump serial execution of tasks /// noseratio - http://stackoverflow.com/a/22262976/1768303 /// </summary> public class messageloopapartment : idisposable { thread _thread; // sta thread taskscheduler _taskscheduler; // sta thread's task scheduler public taskscheduler taskscheduler { { return _taskscheduler; } } /// <summary>messageloopapartment constructor</summary> public messageloopapartment() { var tcs = new taskcompletionsource<taskscheduler>(); // start sta thread , gets task scheduler _thread = new thread(startarg => { eventhandler idlehandler = null; idlehandler = (s, e) => { // handle application.idle once application.idle -= idlehandler; // return task scheduler tcs.setresult(taskscheduler.fromcurrentsynchronizationcontext()); }; // handle application.idle once // make sure we're inside message loop // , synchronizationcontext has been correctly installed application.idle += idlehandler; application.run(); }); _thread.setapartmentstate(apartmentstate.sta); _thread.isbackground = true; _thread.start(); _taskscheduler = tcs.task.result; } /// <summary>shutdown sta thread</summary> public void dispose() { if (_taskscheduler != null) { var taskscheduler = _taskscheduler; _taskscheduler = null; // execute application.exitthread() on sta thread task.factory.startnew( () => application.exitthread(), cancellationtoken.none, taskcreationoptions.none, taskscheduler).wait(); _thread.join(); _thread = null; } } /// <summary>task.factory.startnew wrappers</summary> public void invoke(action action) { task.factory.startnew(action, cancellationtoken.none, taskcreationoptions.none, _taskscheduler).wait(); } public tresult invoke<tresult>(func<tresult> action) { return task.factory.startnew(action, cancellationtoken.none, taskcreationoptions.none, _taskscheduler).result; } public task run(action action, cancellationtoken token) { return task.factory.startnew(action, token, taskcreationoptions.none, _taskscheduler); } public task<tresult> run<tresult>(func<tresult> action, cancellationtoken token) { return task.factory.startnew(action, token, taskcreationoptions.none, _taskscheduler); } public task run(func<task> action, cancellationtoken token) { return task.factory.startnew(action, token, taskcreationoptions.none, _taskscheduler).unwrap(); } public task<tresult> run<tresult>(func<task<tresult>> action, cancellationtoken token) { return task.factory.startnew(action, token, taskcreationoptions.none, _taskscheduler).unwrap(); } } }
Comments
Post a Comment