c# - Background Task sometimes able to update UI? -
i answered question whether task
can update ui. played code, realized i'm not clear myself on few things.
if have windows form 1 control txthello
on it, i'm able update ui task, seems, if on task.run
:
public partial class form1 : form { public form1() { initializecomponent(); task.run(() => { txthello.text = "hello"; }); } }
however if thread.sleep
5 milliseconds, expected crossthread
error thrown:
public partial class form1 : form { public form1() { initializecomponent(); task.run(() => { thread.sleep(5); txthello.text = "hello"; //kaboom }); } }
i'm not sure why happens. there sort of optimization extremely short running task
?
you didn't post exception stack trace, expect looked this:
system.invalidoperationexception: cross-thread operation not valid: control 'textbox1' accessed thread other thread created on. @ system.windows.forms.control.get_handle() @ system.windows.forms.control.set_windowtext(string value) @ system.windows.forms.textboxbase.set_windowtext(string value) @ system.windows.forms.control.set_text(string value) @ system.windows.forms.textboxbase.set_text(string value) @ system.windows.forms.textbox.set_text(string value) @ windowsformsapplicationcsharp2015.form1.<.ctor>b__0_0() in d:\test\windowsformsapplicationcsharp2015\form1.cs:line 27
we can see exception thrown control.handle
getter property. , in fact, if @ source code property, there is, expected:
public intptr handle { { if (checkforillegalcrossthreadcalls && !incrossthreadsafecall && invokerequired) { throw new invalidoperationexception(sr.getstring(sr.illegalcrossthreadcall, name)); } if (!ishandlecreated) { createhandle(); } return handleinternal; } }
the interesting part when @ code calls control.handle
. in case, that's control.windowtext setter property:
set { if (value == null) value = ""; if (!windowtext.equals(value)) { if (ishandlecreated) { unsafenativemethods.setwindowtext(new handleref(window, handle), value); } else { if (value.length == 0) { text = null; } else { text = value; } } } }
notice handle
property invoked if ishandlecreated
true
.
and completeness, if @ code ishandlecreated see following:
public bool ishandlecreated { { return window.handle != intptr.zero; } }
so, reason don't exception, because time task
executes, window handle hasn't been created yet, expected since task
starts in form's constructor, is, before form displayed.
before window handle created, modifying property doesn't yet require work ui thread. during small time window @ start of program, seem possible invoke methods on control instances non-ui thread without getting "cross thread" exception. clearly, existence of special small time window doesn't change fact should make sure invoke control methods ui thread safe.
to prove point timing of window handle creation determining factor in getting (or not) "cross thread" exception, try modifying example force creation of window handle before start task, , notice how consistently expected exception, without sleep:
public partial class form1 : form { public form1() { initializecomponent(); // force creation of window handle var dummy = txthello.handle; task.run(() => { txthello.text = "hello"; // kaboom }); } }
relevant documentation: control.handle
if handle has not yet been created, referencing property force handle created.
Comments
Post a Comment