Sunday, 15 February 2015

wpf - TaskFactory New UI Creation -



wpf - TaskFactory New UI Creation -

how create new ui element using taskfactory? when seek next error :

the calling thread must sta, because many ui components require this.

example code

dim txtboxlist new list(of textbox) sub startthread() dim ts taskscheduler = taskscheduler.fromcurrentsynchronizationcontext() task.factory.startnew(sub() createcontrol(), ts) end sub sub createcontrol() dim txtbox new textbox dispatcher.begininvoke(sub() txtboxlist.add(txtbox)) end sub

if you're working wpf, need leave behind , notions might have learned ancient technologies , understand , encompass the wpf mentality.

basically, never need create or manipulate ui elements in procedural code in wpf. instead, wpf lends heavily utilize databinding.

the wpf threading model not allow create or manipulate instances of ui elements in background threads, , add together them visual tree created "main" ui thread.

anyways, there 0 need such thing, because creating ui elements in cases trivial task can (and must) performed ui thread.

rather worrying visual tree, should concentrate on having data loaded in background threads, , passed datacontext ui can display info accordingly.

this little illustration uses itemscontrol display list of users, loaded asynchronously in background thread , dispatched ui thread display:

<window x:class="wpfapplication7.asyncitemscontrol" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <itemscontrol itemssource="{binding}"> <itemscontrol.itemtemplate> <datatemplate> <border background="lightgray" borderbrush="black" borderthickness="1" margin="2"> <stackpanel> <textblock text="{binding lastname}" margin="2"/> <textblock text="{binding firstname}" margin="2"/> </stackpanel> </border> </datatemplate> </itemscontrol.itemtemplate> </itemscontrol> </window>

code behind:

public partial class asyncitemscontrol : window { public asyncitemscontrol() { initializecomponent(); var dispatcher = taskscheduler.fromcurrentsynchronizationcontext(); task.factory.startnew(() => getusers()) .continuewith(x => datacontext = x.result,dispatcher); } public list<user> getusers() { // pretend method calls web service or database retrieve data, , takes 5 seconds response: thread.sleep(5000); homecoming new list<user> { new user() {firstname = "marty", lastname = "mcfly"}, new user() {firstname = "emmett", lastname = "brown"}, new user() {firstname = "bufford", lastname = "tannen"} }; } }

data item:

public class user { public string lastname { get; set; } public string firstname { get; set; } }

result:

notice illustration uses databinding , not create or manipulate ui elements in procedural code, rather operates simple user class simple string properties.

also notice during 5 seconds "load" time, ui responsive because actual work beingness performed background thread.

this approach allows greater separation between ui , info allows much greater scalability , customizability of ui without having alter underlying business / application logic.

notice how itemscontrol takes care of creating , rendering appropiate ui elements needed display 3 info items. actual definition of "how each item looks" datatemplate.

i recommend reading material linked thoughout reply more in-depth understanding of how wpf works in general.

side note: if you're targetting c# 5.0 can leverage async / await , create code cleaner removing task based stuff. i'm on c# 4.0 feature not available me.

wpf rocks. re-create , paste code in file -> new project -> wpf application , see results yourself.

let me know if need farther help.

wpf vb.net taskfactory

No comments:

Post a Comment