首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在UI线程中更新数据时挂起c# WPF UI

在UI线程中更新数据时挂起c# WPF UI
EN

Stack Overflow用户
提问于 2017-04-24 09:46:47
回答 2查看 1.7K关注 0票数 3

UI冻结3-10秒,而UI线程中的更新数据,我想更新UI线程中的数据而不冻结。

代码:

代码语言:javascript
复制
Task t = Task.Factory.StartNew(() =>
{
    // Get data from Server
    GetData(true);
});

内部Getdata()

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

内部RetriveData

代码语言:javascript
复制
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的最佳方法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-24 10:25:24

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

代码语言:javascript
复制
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());
票数 4
EN

Stack Overflow用户

发布于 2017-04-25 18:00:07

async/await也可以实现同样的结果,它将在完成任务后恢复UI上下文:

代码语言:javascript
复制
// 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,因此您可以这样做:

代码语言:javascript
复制
public async Task<> GetData(...)
{
    // some code ...
    return await Task.Run(() => 
    {
        return RetriveData(tempDataSet, firstTime));
    }
}

要实现这一点,您需要将方法标记为async。如果它是一个事件处理程序,您可以使用async void,在其他情况下可以使用async Task

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43584821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档