Reputation: 691
UI freeze for 3-10 seconds while update data in UI thread I want to update data in UI thread without freeze.
Code:
Task t = Task.Factory.StartNew(() =>
{
// Get data from Server
GetData(true);
});
Inside Getdata()
//Converst JSON to DataSet Object:- "tempDataSet"
Task task = Task.Factory.StartNew(() =>
{
RetriveData(tempDataSet, firstTime);
}, CancellationToken.None, TaskCreationOptions.None, MainFrame.Current);
Inside RetriveData
DataTable response = tempDataSet.Tables["response"];
DataTable conversations = tempDataSet.Tables["convo"];
foreach (DataRow row in conversations.Rows) // UI Hangs in the method
{
UC_InboxControl control = new UC_InboxControl(row, uC_Inbox);
if (uC_Inbox.mnuUnreadChat.IsChecked == false)
{
inboxControlCollection.Add(control);
}
else
{
inboxUnreadOnlyControlCollection.Add(control);
}
}
What is the best approach to update UI in UI thread without hangs or freeze?
Upvotes: 3
Views: 2022
Reputation: 28345
The same result can be achieved with async/await
, which will restore the UI context after completing the task:
// await the task itself, after that do the UI stuff
var collection = await Task.Run(() =>
{
// directly call the retrieve data
return RetriveData(tempDataSet, firstTime);
});
// this code will resume on UI context
foreach (var item in collection)
{
var control = new UC_InboxControl(row, uC_Inbox);
if (!uC_Inbox.mnuUnreadChat.IsChecked)
{
inboxControlCollection.Add(control);
}
else
{
inboxUnreadOnlyControlCollection.Add(control);
}
}
As you can see, I call the RetriveData
directly here. Also you can mark it as async
too, so you can do:
public async Task<> GetData(...)
{
// some code ...
return await Task.Run(() =>
{
return RetriveData(tempDataSet, firstTime));
}
}
To achieve this you need to mark the method as async
. If it is a event handler, you can use async void
, in other case use async Task
.
Upvotes: 0
Reputation: 169160
The GetData
method should not access any UI elements. It should be executed on a background thread and return a list of objects that you want to display in the view. You could then use the ContinueWith
method to populate the ObservableCollection
with these objects back on the UI thread, e.g.:
Task t = Task.Factory.StartNew(() =>
{
return GetData(true); // <-- GetData should return a collection of objects
}).ContinueWith(task =>
{
//that you add to your ObservableCollection here:
foreach (var item in task.Result)
yourObservableCollection.Add(item);
},
System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
Upvotes: 4