Retour d’une tâche sans bloquer le thread d’interface utilisateur

J’ai une méthode qui retourne un datatable. J’ai besoin de tous les trucs SQL pour fonctionner dans un thread et pouvoir ensuite renvoyer un datatable sans bloquer le thread de l’interface utilisateur. De ma compréhension, lorsque vous appelez Task.Result, il bloque le thread d’interface utilisateur jusqu’à ce que la tâche soit terminée. Comment pourrais-je contourner cela. J’ai lu des articles sur l’utilisation de wait et async, mais je n’ai pas encore compris comment l’utiliser avec la tâche.

public static DataTable LaunchLocationMasterListReport(ObservableCollection BuiltConditionsList, ObservableCollection BuiltSortList, ObservableCollection ColumnsForReport, bool LocationNotesCheckBox, ref ssortingng reportQuery, ref ssortingng reportQueryforSave, ref ssortingng reportView, ref ssortingng queryCondtions) { queryCondtions = BuildConditionAndSorts(queryCondtions, BuiltConditionsList, BuiltSortList); reportQueryforSave = "SELECT * FROM LocationMasterReportView"; reportView = "LocationMasterReportView"; reportQuery = "SELECT * FROM LocationMasterReportView " + queryCondtions; return LaunchReport(reportQuery, ColumnsForReport).Result; } async private static Task LaunchReport(ssortingng reportQuery, ObservableCollection ColumnsForReport) { SqlConnection myConn = new SqlConnection(Settings.Default.UltrapartnerDBConnectionSsortingng); DataTable dt = new DataTable(); ssortingng rq = reportQuery; Task task = Task.Factory.StartNew(() => { using (SqlCommand comm = new SqlCommand(rq, myConn)) { myConn.Open(); dt.Load(comm.ExecuteReader()); myConn.Close(); } if (dt.Rows.Count == 0) { MessageBox.Show("Contains No Results"); return null; } foreach (ListBoxCheckBoxItemModel lbc in ColumnsForReport) { if (!lbc.IsSelected) { dt.Columns.Remove(lbc.Name.ToSsortingng()); } } return dt; }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); return await task; } 

Je conviens que l’utilisation async / wait est la meilleure approche ici. Comme indiqué précédemment, lorsque vous attendez une méthode asynchrone, même si le type de retour déclaré est une tâche , le compilateur traduit cela en un type de retour implicite de T.

Le piège est que toutes les méthodes asynchrones doivent retourner void, Task ou Task . Donc, une fois que vous commencez à les utiliser, vous devez “masquer” l’atsortingbut de méthode “asynchrone” jusqu’à atteindre un point où vous pouvez bloquer le résultat ou votre méthode peut être annulée ou Task (c’est-à-dire que vous avez consommé la résultat).

Veuillez voir cet exemple simple basé sur une interface utilisateur:

 ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private async void Button_Click(object sender, RoutedEventArgs e) { statusText.Text = "Running"; statusText.Text = await _ComputeText(true); statusText.Text = await _ComputeText(false); } private static async Task _ComputeText(bool initialTask) { ssortingng result = await Task.Run(() => { Thread.Sleep(2000); return initialTask ? "Task is done!" : "Idle"; }); return result; } } 

Notez que le gestionnaire d’événements de bouton, “Button_Click”, est simplement déclaré comme “void” return. Mais je peux le faire car je consum le résultat asynchrone de cette méthode.

Dans votre cas, le DataTable renvoyé n’est pas disponible tant que la tâche asynchrone n’est pas terminée. Vous devez donc déclarer chaque méthode comme “asynchrone”, quelle que soit la méthode utilisée pour faire quelque chose avec le DataTable. Même là, la méthode devra être déclarée comme asynchrone, mais vous ne retournerez pas le DataTable et cette méthode peut donc avoir un type de retour de type “void” ou “Task”. Un scénario courant est que cette méthode soit un gestionnaire d’événements d’interface utilisateur. Par conséquent, “void” devrait être correct (et sera nécessaire pour être utilisé dans un délégué de gestionnaire d’événements); votre code ne l’appelle pas quand même. Mais il est techniquement plus correct d’utiliser “Tâche” à la place, donc si dans votre contexte cela fonctionne, vous devriez le faire de cette façon.

Sans un exemple concis mais complet, il est difficile d’offrir quelque chose de plus spécifique que cela.