IronPython WebbrowserControl - form creation issue
I'm using IronPython 2.6 and a WebbrowserControl on a form called TridentForm. This is used for displaying reports, etc.
The main form, LaunchForm, has a button that has an OnClick event handler. This event handler sets some stuff up and then kicks off a BackgroundWorker. The Background worker completes, and in this callback it instantiates TridentForm, shows it, etc, etc.
Now This works fine, here's an abridged current code:
class LaunchForm(Form):
def __init__(self):
#blah blah, InitilizeComponents(), blah
self.form_splash = None
self.form_report = None
self._report_worker = BackgroundWorker()
self._report_worker.DoWork += self.runReport
self._report_worker.RunWorkerCompleted += self.runReport_finished
def runReport_handler(self, sender, args):
self._report_worker.RunWorkerAsync(job_type)
log.debug("renReport_handler called on thread %s"%(Thread.CurrentThread.ManagedThreadId))
def runReport(self, sender, args): #run by a backgroundworker
#do stuff, doesn't matter
def runReport_finished(self, sender, args):
#error checking, etc
log.debug("reunReport_finished called on thread %s"%(Thread.CurrentThread.ManagedThreadId))
if not self.form_report:
log.debug("Creating TridentForm")
self.form_report = TridentForm()
log.debug("Getting TridentForm")
vf = self.form_report
As you can see, self.form_report (TridentForm) is reused after it's first creation. The reason for this is that between the log statements "Creating TridentForm" and "Getting TridentForm" up to 7 seconds is spent doing (seemingly) nothing. The log tells no lies. Anyway, I assume that this is component init time for IE's ActvieX control.
Obviously, I don't want to be waiting 7 seconds on this.
So, I decided to try creating the form at the end of runReport_handler - it'll make the UI freeze a bit, but the background thread is working, so no biggie. Note the logging statements about the thread IDs - i've confirmed that both runReport_handler and runReport_finished get called on the same thread.
So, my problem: Simply moving that creation up to the end of runReport_handler gives me several fun unhandled thread exceptions:
Traceback (most recent call last):
File "C:\completely\unrelated\control\subclass\used\on\the\mainform.py", line 33, in OnMouseUp
TypeError: cannot access protected member OnMouseUp without a python subclass of Control
Microsoft.Scripting.ArgumentTypeException: cannot access protected member OnMouseUp without a python subclass of Control
at IronPython.Runtime.Types.BuiltinFunction.<>c__DisplayClass6.<MakeBuiltinFunctionDelegate>b__0(Object[] callArgs, Boolean& shouldOptimize)
at IronPython.Runtime.Types.BuiltinFunction.BuiltinMethodCaller`2.Call1(CallSite site, CodeContext context, TFuncType func, T0 arg0)
at Microsoft.Scripting.UpdateDelegates.UpdateA开发者_高级运维ndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at Microsoft.Scripting.Interpreter.DynamicInstruction`4.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.LightLambda.Run3[T0,T1,T2,TRet](T0 arg0, T1 arg1, T2 arg2)
at IronPython.Compiler.PythonCallTargets.OriginalCallTarget2(PythonFunction function, Object arg0, Object arg1)
at IronPython.Runtime.PythonFunction.FunctionCaller`2.Call2(CallSite site, CodeContext context, Object func, T0 arg0, T1 arg1)
at Microsoft.Scripting.UpdateDelegates.UpdateAndExecute4[T0,T1,T2,T3,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
at IronPython.Runtime.PythonFunction.FunctionCaller`2.Default1Call2(CallSite site, CodeContext context, Object func, T0 arg0, T1 arg1)
at CallSite.Target(Closure , CallSite , CodeContext , Object , Object )
at Microsoft.Scripting.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at IronPython.NewTypes.System.Windows.Forms.Control_13$14.OnMouseUp(MouseEventArgs )
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at IronPython.NewTypes.System.Windows.Forms.Control_13$14.WndProc(Message& )
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
and
Traceback (most recent call last):
File "C:\TridentForm.py", line 159, in TridentNavigating
TypeError: cannot access protected member OnMouseUp without a python subclass of Control
Microsoft.Scripting.ArgumentTypeException: cannot access protected member OnMouseUp without a python subclass of Control
at IronPython.Runtime.Types.BuiltinFunction.<>c__DisplayClass6.<MakeBuiltinFunctionDelegate>b__0(Object[] callArgs, Boolean& shouldOptimize)
at IronPython.Runtime.Types.BuiltinFunction.BuiltinMethodCaller`2.Call1(CallSite site, CodeContext context, TFuncType func, T0 arg0)
at Microsoft.Scripting.Interpreter.DynamicInstruction`4.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.LightLambda.Run3[T0,T1,T2,TRet](T0 arg0, T1 arg1, T2 arg2)
at IronPython.Runtime.PythonFunction.FunctionCaller`2.Call2(CallSite site, CodeContext context, Object func, T0 arg0, T1 arg1)
at CallSite.Target(Closure , CallSite , CodeContext , Object , Object )
at IronPython.NewTypes.System.Windows.Forms.Control_13$14.OnMouseUp(MouseEventArgs )
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at IronPython.NewTypes.System.Windows.Forms.Control_13$14.WndProc(Message& )
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Both of which don't make any sense. As a bonus, now clicking on the main form produces that message too.
The refered to exceptions:
line 33 of the unrelated control:
def OnMouseUp(self, e): self.pressed = False if self.image_down: self.Invalidate() super(SimpleImageButton, self).OnMouseUp(e) #dies here. Yes, this is a subclass of Control.
and the TridentForm code:
def TridentNavigating(self, sender, e): if e.Url != self.dest_url and e.Url != PLEASE_WAIT_URL: #dies here. self is a Form, which I guess is a subclass of Control. But still, none of the things in this line ever touch clr types - self.dest_url is a python attribute
So, I'm lost.
Alternatively, if you could sugegst a way to "preload" TridentForm some other way, that'd be great. Thanks. e.Cancel = true
Ugh, it was the super() call... Sorry for wasting everyone's time :)
精彩评论