2017-11-23 6 views
2

ここで、ローカルサーバーからExcelにデータをエクスポートする必要があります。私はその方法のためにasync呼び出しを使用しています。しかし、それでも、データをエクスポートしながらUIをブロックしています。asyncを使用中にUIがブロックされ、Cで待機する#

UIがブロックされている理由を知ることができますか?

はまた、私は

1)awaitキーワードは、プロセスが完了 するまである程度の時間を待つために使用されるいくつかの明確化が必要で、その後、B同期と 非同期プロセスワット/ 違いは何ですか。

2)1つのメソッドがAsyncタスクとして宣言されている場合、すべての内部メソッド は非同期として実行していますか?

3)内部メソッド(method1、method2、method3)を実行しているとき、method3はとなりますが、method1に依存します。したがって、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

あなたの 'async'メソッドは何も' await'しません。また、 'async'メソッドからの戻り値の型は' Task'でなければなりません。 – Adwaenyth

+3

メソッドは非同期ではありません。なぜなら、実際にはタスクやそれに類するものは何もしないからです。 'async'を追加するだけで魔法のように非同期にならないので、' await'とタスクも使う必要があります。 –

答えて

0

は、あなたがそのようなSQLサーバとの非同期通信を使用するようにコードを変更することができます

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

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

こんにちは@ lzikon、私もこの1つを試してみてください。同じ問題が発生します。 – Pandi

0

を試してみました:

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より大きい場合はブロックされます。

+0

こんにちは@マイケル、私は50,000,000以上のSQL Serverのレコードを持っています。 UIをブロックする理由はありますか? – Pandi

+0

SQLクエリを実行してディスクにファイルを書き込むときに、実行中のスレッドが初期コードによってブロックされました。 SQLサーバーの操作を非同期にしましたが、データをDataTableにロードして新しいファイルをディスクに書き込むことは、同期して実行されます。別のスレッドでこの操作を実行すると、UIがフリーズしないようにすることができます。 – Michael

+0

[Task.Run](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=netframework-4.7.1#System_Threading_Tasks_Task_Run_System_Func_System_Threading_Tasks_Task__)メソッドをチェックすると、スレッドからタスクを作成します。 – Michael

2

1)awaitキーワードは、プロセスが完了するまでしばらく待機していますが、次にb/wの同期および非同期プロセスの違いは何ですか。

同期:ブロックスレッドを待っているので、UI
非同期ロック:、一つの方法は、非同期タスクとして宣言されている場合ので、UI

2)をブロックしない、待機スレッドを解放しますすべての内部メソッドが非同期として実行されていますか?

これは当てはまりません。おそらくそのようにしたいと思うかもしれませんが、それをコード化するのは開発者としての責任です。
コンプライアーはこれを強制するものではありません。

上記のコードでは、答えはいいえです。あなたのコードは非同期ではありません。 awaitキーワードを使用しないことに注意してください。
最初に非同期の方法でデータにアクセスする必要があります(タスクを返す)。そうしないと、async/awaitキーワードはあなたを助けません。

3)内部メソッド(method1、method2、method3)を実行しているとき、method3はmethod1に依存します。だから、method1のキーワードawaitを入れてください。私は正しい?

はい。各メソッドがTaskを返す場合は、すべてのメソッドを待機します。 通常、ある場所でawaitを使用し始めると、コードの残りの部分がバブルアップしますので、あなたが記述した通りにさらに待っていきます。

+0

もし私が待っているなら、それはその操作が完了するのを待つでしょう。それは同期的なもののように振る舞います。そして、待つ前と待った後の違いは何ですか? – Pandi

+1

具体的なケースでは違いはありません。 'await'はすでに非同期のコードでしか動作しません。データベース呼び出しが同期から非同期に変わることは魔法のようにはありません。非同期DB呼び出しを検索したいとします(たとえば、 'command.ExecuteReaderAsync()') –

+0

Okay buh buh。私は明らかに理解しています。ありがとう – Pandi

関連する問題