WPF – TaskFactory New UI creation

How to use TaskFactory to create new UI elements? When I try, I get the following error:

The calling thread must be STA, because many UI components need this.

Sample code

Dim txtBoxList as new List(Of TextBox)

Sub StartThread()
Dim TS As TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
Task.Factory .StartNew(Sub() CreateControl(), TS)
End Sub

Sub CreateControl()
Dim txtBox As New TextBox
Dispatcher.BeginInvoke(Sub() txtBoxList.Add(txtBox))
End Sub

If you are using WPF, you Really need to leave any and all concepts you may have learned from ancient technology, and understand and embrace The WPF Mentality.

Basically, you hardly need Create or manipulate UI elements in the process code in WPF. On the contrary, WPF helps to use DataBinding a lot.

The WPF Threading Model is not allowed You create or manipulate instances of UI elements in a background thread and add them to the Visual Tree created by the “main” UI thread.

Anyway, for such a Things are almost unnecessary, because creating UI elements is a simple task in most cases and can (and must) be performed by the UI thread.

You should not worry about Visual Tree, but should focus on data Load it into a background thread, and then pass it to the UI as a DataContext so that it can display your data accordingly.

This is a small example, it uses ItemsControl displays a list of users, these user lists are loaded asynchronously in a background thread, and then dispatched to the UI thread for display:

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas .microsoft.com/winfx/2006/xaml">












Behind the code:

public partial class AsyncItemsControl: Window
{
public AsyncItemsControl()
{
InitializeComponent();

var dispatcher = TaskScheduler.FromCurrentSynchronizationContext();

Task.Factory.StartNew(() => GetUsers())
.ContinueWith(x => DataContext = x.Result,dispatcher);

}

public List GetUsers()
{
// pretend this method calls a Web Service or Database to retrieve the data, and it takes 5 seconds to get a response:
Thread.Sleep(5000);

return new List
{
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:

>Please note that this example uses DataBinding, it does not create or manipulate UI elements in the process code, but uses simple string attributes Simple User class to operate.
>Please also note that within 5 seconds of “loading” time, the UI responds, because the actual work is performed by a background thread.
>This method allows greater separation between UI and data , Which allows greater extensibility and customizability of the UI without changing the underlying business/application logic.
>Note how ItemsControl handles the creation and presentation of the appropriate UI elements required to display the 3 data items. “Each The actual definition of “how a project looks like” is DataTemplate.> I strongly recommend that you read the material linked in this answer to gain a deeper understanding of how WPF works.> Side note: If your goal It’s C#5.0, you can take advantage of async/await and make the code clearer by removing all task-based things. I’m on C#4.0, so I can’t use the feature.> WPF Rocks. Just copy my code And paste it into the file -> new project -> WPF application and see the result yourself.>If you need further help, please let me know.

How to create with TaskFactory New UI elements? When I try, I get the following error:

The calling thread must be STA, because many UI components need this.

Sample code

Dim txtBoxList as new List(Of TextBox)

Sub StartThread()
Dim TS As TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
Task.Factory .StartNew(Sub() CreateControl(), TS)
End Sub

Sub CreateControl()
Dim txtBox As New TextBox
Dispatcher.BeginInvoke(Sub() txtBoxList.Add(txtBox))
End Sub

If you are using WPF, you really need to leave what you may have learned from ancient technology Any and all concepts, and understand and embrace The WPF Mentality.

Basically, you hardly need to create or manipulate UI elements in the process code in WPF On the contrary, WPF helps to use DataBinding extensively.

The WPF Threading Model does not allow you to create or manipulate instances of UI elements in a background thread , And add them to the Visual Tree created by the “main” UI thread.

Anyway, there is almost no need for such things, because creating UI elements in most The situation is a simple task that can (and must) be performed by the UI thread.

You should not worry about Visual Tree, but should focus on loading data into a background thread, and then use it as a DataContext is passed to the UI so that it can display your data accordingly.

This is a small example, it uses ItemsControl Display a list of users, these user lists are loaded asynchronously in a background thread, Then dispatch to the UI thread for display:

 xmlns="http://schemas.microsoft.com/ winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">












Behind the code:

public partial class AsyncItemsControl: Window
{
public AsyncItemsControl()
{
InitializeComp onent();

var dispatcher = TaskScheduler.FromCurrentSynchronizationContext();

Task.Factory.StartNew(() => GetUsers())
.ContinueWith( x => DataContext = x.Result,dispatcher);

}

public List GetUsers()
{
// pretend this method calls a Web Service or Database to retrieve the data, and it takes 5 seconds to get a response:
Thread.Sleep(5000);

return new List
{
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:

>Please note that this example uses DataBinding, it does not create or manipulate UI elements in the process code, but uses tools Simple User class with simple string attributes to operate.
>Please also note that within 5 seconds of “loading” time, the UI responds, because the actual work is performed by a background thread.
>This method allows UI and data Greater separation between the UI, which allows for greater scalability and customizability of the UI without changing the underlying business/application logic.
>Note how ItemsControl handles the creation and presentation of the 3 data items required Appropriate UI elements. The actual definition of “how each item looks” is DataTemplate.> I strongly recommend that you read the material linked in this answer to gain a deeper understanding of how WPF works.> Note: If your target is C#5.0, you can take advantage of async/await and make the code clearer by removing all task-based stuff. I’m on C#4.0, so I can’t use the feature.> WPF Rocks. Only I need to copy and paste my code into the file -> New Project -> WPF application and see the result personally.>If you need further help, please let me know.

p>

Leave a Comment

Your email address will not be published.