【发布时间】:2014-12-14 17:52:17
【问题描述】:
我有一个返回数据表的方法。我需要所有的 sql 东西在一个线程中运行,然后能够在不阻塞 UI 线程的情况下传回一个数据表。据我了解,当您调用 Task.Result 时,它会阻塞 UI 线程,直到任务完成。我将如何解决这个问题。我阅读了有关使用 await 和 async 的信息,但我还没有完全弄清楚如何在任务中使用它。
public static DataTable LaunchLocationMasterListReport(ObservableCollection<string> BuiltConditionsList, ObservableCollection<string> BuiltSortList, ObservableCollection<ListBoxCheckBoxItemModel> ColumnsForReport,
bool LocationNotesCheckBox, ref string reportQuery, ref string reportQueryforSave, ref string reportView, ref string 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<DataTable> LaunchReport(string reportQuery, ObservableCollection<ListBoxCheckBoxItemModel> ColumnsForReport)
{
SqlConnection myConn = new SqlConnection(Settings.Default.UltrapartnerDBConnectionString);
DataTable dt = new DataTable();
string rq = reportQuery;
Task<DataTable> 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.ToString());
}
}
return dt;
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
return await task;
}
【问题讨论】:
-
在任务中使用
async和await很简单:将async添加到您的方法签名中,将返回类型更改为Task<DataTable>,并将return task.Result替换为return task。您可能需要将调用此方法的代码重构为async,以便您可以await得到结果(这会为您提供DataTable而不是任务)。阅读更多关于该主题的内容——这绝对值得。 -
不要使用
task.Result。这是一个阻塞调用。请改用return await task。 (顺便说一句:您的方法签名将类似于async public Task<DataTable> Launch) -
我必须使用 .Result 一些方法来找回
DataTable,对吗?让我用我所拥有的更新代码。
标签: c# wpf multithreading task