繁体   English   中英

不使用异步和等待阻止UI

[英]Without blocking UI using async and await

我的要求是,需要使用async和await渲染与数据绑定的所有框架元素。

尝试以下可能性:

  1. 如果我使用asyncmethod().result ,它将阻止UI,并且将等待很长时间才能完成。

  2. 如果我使用的是await关键字,则在完成parallel.foreach()之前将先击中controlstoconfigure foreach(第二个

所以,可以请你建议我要渲染的元素,要求每个第二并行的foreach结束后或不阻塞UI?

程式码片段:

1)Renderingwidget-此方法用于获取与数据绑定的集合中的框架元素。

2)FetchData-此方法用于从服务器获取特定框架元素的数据。

3)GetTablefromserver-此方法用于基于查询获取数据。

    public async void RenderingWidget()
    {
        ConcurrentDictionary<string, EngineChangedEventArgs> controlsToConfigure = new ConcurrentDictionary<string, EngineChangedEventArgs>();
        foreach (var engines in MainWindow.ViewModel.RelationalDataManagerList.Values)
        {
            Dictionary<string, FrameworkElement> controlcollection = CurrentDashboardReport.WidgetCollection;
            Parallel.ForEach(controlcollection, async item =>
             {
                 try
                 {
                     try
                     {
                         controlsToConfigure.TryAdd(item.Key, await FetchDataInParallel(MainWindow.ViewModel.RelationalDashboardReportList[engines.DataSourceName].Reports, item.Key,));
                     }
                     catch (Exception ex)
                     {
                         ExceptionLog.WriteExceptionLog(ex, null);
                         throw new ParallelException(ex, item.Key);
                     }
                 }
                 catch (ParallelException ex)
                 {
                     exceptions.Enqueue(ex);
                     ExceptionLog.WriteExceptionLog(ex, GeneratedQueryText);
                 }
             });
            if (exceptions.Count > 0)
            {
                foreach (var nonRenderedControls in exceptions)
                {
                    controlsToConfigure.TryAdd(nonRenderedControls.ReportName, await FetchDataInParallel(CurrentDashboardReport.Reports, nonRenderedControls.ReportName));
                }
            }
        }
        foreach (var control in controlsToConfigure)
        {
            (CurrentDashboardReport.WidgetCollection[control.Key] as DashboardDataControl).CurrentDashboardReport.OnActiveColumnsChanged(control.Value);                   
        }
    }

    public async Task<EngineChangedEventArgs> FetchDataInParallel(RelationalReportCollection reports, string myReport)
    {
        var dataTable = await GetTableFromServer(reports.Query);
        eventArgs = new EngineChangedEventArgs
        {
            ItemsSource = dataTable
        };
        return eventArgs;
    }

    public async Task<DataTable> GetTableFromServer(string query)
    {
        var resultTable = new DataTable
        {
            Locale = CultureInfo.InvariantCulture
        };
        SqlConnection sqlConnection = new SqlConnection(connectionString);
        SqlCommand command = new SqlCommand(query, sqlConnection)
        SqlDataReader dataReader = null;
        try
        {
            if (sqlConnection.State != ConnectionState.Open)
            {
                sqlConnection.Open();
            }
            dataReader =await command.ExecuteReaderAsync();
            resultTable.Load(dataReader);
            return resultTable;
        }
        finally
        {
            if (dataReader != null)
            {
                dataReader.Dispose();
            }
            command.Dispose();
            return resultTable;
        }
    }

当您在async调用期间释放线程时, Parallel.ForEachasync / await配合不佳。 有关此问题的更多信息,请参考以下问题: 在Parallel.ForEach中嵌套等待

您可以只在线程池线程上调用Parallel.ForEach ,然后使用Task.WhenAll方法等待所有任务完成,然后再继续:

public async void RenderingWidget()
{
    ConcurrentDictionary<string, EngineChangedEventArgs> controlsToConfigure = new ConcurrentDictionary<string, EngineChangedEventArgs>();

    List<Task> tasks = new List<Task>();

    foreach (var engines in MainWindow.ViewModel.RelationalDataManagerList.Values)
    {
        Dictionary<string, FrameworkElement> controlcollection = CurrentDashboardReport.WidgetCollection;
        tasks.Add(Task.Run(() =>
        {
            Parallel.ForEach(controlcollection, item =>
            {
                try
                {
                    try
                    {
                        controlsToConfigure.TryAdd(item.Key, FetchDataInParallel(MainWindow.ViewModel.RelationalDashboardReportList[engines.DataSourceName].Reports, item.Key).Result);
                    }
                    catch (Exception ex)
                    {
                        ExceptionLog.WriteExceptionLog(ex, null);
                        throw new ParallelException(ex, item.Key);
                    }
                }
                catch (ParallelException ex)
                {
                    exceptions.Enqueue(ex);
                    ExceptionLog.WriteExceptionLog(ex, GeneratedQueryText);
                }
            });
            if (exceptions.Count > 0)
            {
                foreach (var nonRenderedControls in exceptions)
                {
                    controlsToConfigure.TryAdd(nonRenderedControls.ReportName, FetchDataInParallel(CurrentDashboardReport.Reports, nonRenderedControls.ReportName).Result);
                }
            }
        }));
    }

    await Task.WhenAll(tasks);

    foreach (var control in controlsToConfigure)
    {
        (CurrentDashboardReport.WidgetCollection[control.Key] as DashboardDataControl).CurrentDashboardReport.OnActiveColumnsChanged(control.Value);
    }
}

public async Task<EngineChangedEventArgs> FetchDataInParallel(RelationalReportCollection reports, string myReport)
{
    var dataTable = await GetTableFromServer(reports.Query).ConfigureAwait(false);
    return new EngineChangedEventArgs
    {
        ItemsSource = dataTable
    };
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM