在使用async时会阻止UI并在c#

时间:2017-11-23 11:41:44

标签: c# asynchronous async-await task ui-thread

这里我需要将一些数据从本地服务器导出到Excel中。我正在使用async调用该方法。但是,它仍然在导出数据时阻止了用户界面。

我可能知道UI被阻止的原因吗?

另外,我需要一些澄清

  

1)await关键字用于等待一段时间,直到该过程为止   完成,然后差异b / w同步和   异步过程

     

2)如果一个方法被声明为Async任务,那么所有内部方法   表现为异步?

     

3)执行内部方法(method1,method2,method3)时,method3将执行   取决于方法1。因此,为method1添加await关键字。我   正确?

代码段:

private async void ConvertExcel(object sender)
{
    var excelEngine = new ExcelEngine();
    var application = excelEngine.Excel;
    var newbookWorkbook = application.Workbooks.Create(1);
    var work = newbookWorkbook.Worksheets[0];
    var openDialog = new SaveFileDialog
    {
        FilterIndex = 2,
        Filter = "Excel 97 to 2003 Files(*.xls)|*.xls|Excel 2007 to 2013 Files(*.xlsx)|*.xlsx"
    };
    if (openDialog.ShowDialog() == true)
    {
        newbookWorkbook.Version = openDialog.FilterIndex == 1 ? ExcelVersion.Excel97to2003 : ExcelVersion.Excel2013;
    }
    else
        return;
    try
    {            
         // This method is used to get the data from server.          
         var table =  GetFullDataAsync();
         work.ImportDataTable(table, true, 1, 1, true);
         using (Stream stream = openDialog.OpenFile())
         {
            newbookWorkbook.SaveAs(stream);
         }

         newbookWorkbook.Close();
         excelEngine.Dispose();
    }
    catch (Exception exception)
    {
       Console.WriteLine("Exception message: {0}",ex.Message);
    }
}

internal async Task<DataTable> GetFullDataAsync()
{
    DataTable dataTable = new DataTable();
    dataTable = GetDataFromServer(DataEngine.Query,DataEngine.Connection);

    dataTable.Locale = CultureInfo.InvariantCulture;
    return dataTable;
}        


public DataTable GetDataFromServer(string query, DbConnection connection)
{
    if (connection.State != ConnectionState.Open)
    {
        connection.Open();
    }

    var command = connection.CreateCommand();
    command.CommandText = query; 
    command.Connection = connection;

    var reader = command.ExecuteReader();
    var dataTable = new DataTable
    {
        Locale = System.Globalization.CultureInfo.InvariantCulture
    };
    dataTable.Load(reader);
    return dataTable;
}

3 个答案:

答案 0 :(得分:2)

  

1)await关键字用于等待一段时间直到进程完成,然后b / w同步和异步进程有什么区别。

同步:等待阻塞线程,所以锁定ui
异步:等待释放线程,因此不会阻止ui

  

2)如果一个方法被声明为异步任务,那么所有内部方法都以异步方式执行?

不要认为这是真的。您可能希望情况如此,但作为开发人员,您可以通过这种方式对其进行编码 编译器不会为您强制执行此操作。

在上面的代码中,答案是否定的;你的代码不是异步的。请注意,您从不使用await关键字 您可能需要首先以异步方式访问数据(返回任务),否则async / await关键字无法帮助您。

  

3)执行内部方法(method1,method2,method3)时,method3将取决于method1。因此,为method1设置await关键字。我是对的吗?

是。如果每个方法都返回一个Task,那么等待它们全部。 通常当你在一个地方开始使用await时,它会在你的其余代码中冒出来,所以你不断添加更多的东西等等。

答案 1 :(得分:0)

你试过吗

GetFullDataAsync().ContinueWith((table)=>{
      work.ImportDataTable(table, true, 1, 1, true);
         using (Stream stream = openDialog.OpenFile())
         {
            newbookWorkbook.SaveAs(stream);
         }

         newbookWorkbook.Close();
         excelEngine.Dispose();
})

答案 2 :(得分:0)

您可以更改代码以使用与Sql server的异步通信:

private async Task ConvertExcel(object sender)
{
    var excelEngine = new ExcelEngine();
    var application = excelEngine.Excel;
    var newbookWorkbook = application.Workbooks.Create(1);
    var work = newbookWorkbook.Worksheets[0];
    var openDialog = new SaveFileDialog
    {
        FilterIndex = 2,
        Filter = "Excel 97 to 2003 Files(*.xls)|*.xls|Excel 2007 to 2013 Files(*.xlsx)|*.xlsx"
    };
    if (openDialog.ShowDialog() == true)
    {
        newbookWorkbook.Version = openDialog.FilterIndex == 1 ? ExcelVersion.Excel97to2003 : ExcelVersion.Excel2013;
    }
    else
        return;
    try
    {            
         // This method is used to get the data from server.          
         var table = await GetFullDataAsync();
         work.ImportDataTable(table, true, 1, 1, true);

         var saveWorkbookTask = Task.Run(() => {
             using (Stream stream = openDialog.OpenFile())
             {
                newbookWorkbook.SaveAs(stream);
             }
         });

         await saveWorkbookTask;

         newbookWorkbook.Close();
         excelEngine.Dispose();
    }
    catch (Exception exception)
    {
       Console.WriteLine("Exception message: {0}",ex.Message);
    }
}

internal async Task<DataTable> GetFullDataAsync()
{
    DataTable dataTable = new DataTable();
    dataTable = await GetDataFromServer(DataEngine.Query,DataEngine.Connection);

    dataTable.Locale = CultureInfo.InvariantCulture;
    return dataTable;
}        


public async Task<DataTable> GetDataFromServer(string query, DbConnection connection)
{
    if (connection.State != ConnectionState.Open)
    {
        connection.Open();
    }

    var command = connection.CreateCommand();
    command.CommandText = query; 
    command.Connection = connection;

    var reader = await command.ExecuteReaderAsync();

    var loadTableTask = Task.Run(() => {
        var dataTable = new DataTable
        {
            Locale = System.Globalization.CultureInfo.InvariantCulture
        };
        dataTable.Load(reader);
        return dataTable;
    });

    return await loadTableTask;
}

但是你仍然有阻止IO操作。因此,如果您的文件很大,则在将文件写入磁盘时将阻止UI。