2017-04-24 58 views
3

UI冻结3-10秒,同时更新UI线程中的数据我想在不冻结的情况下更新UI线程中的数据。c#WPF UI在UI线程中更新数据时挂起

代码:

Task t = Task.Factory.StartNew(() => 
{ 
    // Get data from Server 
    GetData(true); 
}); 

Getdata()

//Converst JSON to DataSet Object:- "tempDataSet" 
Task task = Task.Factory.StartNew(() => 
{    
    RetriveData(tempDataSet, firstTime); 
}, CancellationToken.None, TaskCreationOptions.None, MainFrame.Current); 

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); 
    } 
} 

什么是更新UI线程UI没有挂起或冻结的最佳方法?

+0

你为什么要在Getdata()里面开始一个新的任务?请发布完整的代码。 – mm8

+0

里面的RetriveData有UI操作,我使用了新的UI任务更新 –

+0

GetData中有哪些UI操作?这没有意义。所有的UI操作都会冻结UI线程。 – mm8

回答

3

GetData方法不应该访问任何UI元素。它应该在后台线程上执行并返回要在视图中显示的对象列表。然后,您可以使用ContinueWith方法来填充ObservableCollection与这些对象后面的UI线程上,例如:

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()); 
+1

感谢您每次帮助我... –

+0

不客气:) – mm8

0

同样的结果可以用async/await来实现,完成任务后,将恢复UI方面:

// 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); 
    } 
} 

正如你所看到的,我直接在这里打电话给RetriveData。你也可以将它标记为async,所以你可以这样做:

public async Task<> GetData(...) 
{ 
    // some code ... 
    return await Task.Run(() => 
    { 
     return RetriveData(tempDataSet, firstTime)); 
    } 
} 

要做到这一点,你需要标记方法async。如果是事件处理程序,则可以使用async void,在其他情况下使用async Task

+0

会尝试并提供反馈谢谢 –