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

c#WPF UI在UI线程中更新数据时挂起,c#,wpf,multithreading,C#,Wpf,Multithreading,用户界面冻结3-10秒,同时更新用户界面线程中的数据我想更新用户界面线程中的数据而不冻结 代码: 内部Getdata() 内部检索数据 //Converst JSON to DataSet Object:- "tempDataSet" Task task = Task.Factory.StartNew(() => { RetriveData(tempDataSet, firstTime); }, CancellationToken.None, TaskCr

用户界面冻结3-10秒,同时更新用户界面线程中的数据我想更新用户界面线程中的数据而不冻结

代码:

内部
Getdata()

内部
检索数据

//Converst JSON to DataSet Object:- "tempDataSet"
Task task = Task.Factory.StartNew(() =>
{             
    RetriveData(tempDataSet, firstTime);
}, CancellationToken.None, TaskCreationOptions.None, MainFrame.Current);
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而不挂起或冻结的最佳方法是什么?

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

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());
Task t=Task.Factory.StartNew(()=>
{
返回GetData(true);//
{
//您在此处添加到您的ObservableCollection中:
foreach(task.Result中的变量项)
您的ObservableCollection.Add(项目);
},
System.Threading.CancellationToken.None,TaskContinuationOptions.None,TaskScheduler.FromCurrentSynchronizationContext();

使用
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);
    }
}
如您所见,我在这里直接调用
retrievedata
。您也可以将其标记为
async
,因此您可以执行以下操作:

public async Task<> GetData(...)
{
    // some code ...
    return await Task.Run(() => 
    {
        return RetriveData(tempDataSet, firstTime));
    }
}
公共异步任务GetData(…) { //一些代码。。。 返回等待任务。运行(()=> { 返回检索数据(tempDataSet,第一次)); } }
要实现这一点,您需要将该方法标记为
async
。如果它是一个事件处理程序,您可以使用
async void
,在其他情况下使用
async Task

为什么要在Getdata()中启动新任务?请发布完整的代码。在RetrieveData中,有一些UI操作是我使用new task进行UI更新的。GetData中有哪些UI操作?这毫无意义。所有UI操作都将冻结UI线程。在GetData中,我首先向服务器请求并从服务器获取数据。在此之后,我将JSON数据转换为DATASET,然后我调用l“RetrieveData”方法和内部“RetrieveData”…我更新我的observationcollection变量以及什么是大型机。当前?
public async Task<> GetData(...)
{
    // some code ...
    return await Task.Run(() => 
    {
        return RetriveData(tempDataSet, firstTime));
    }
}