gpt4 book ai didi

c# - 从任务返回而不阻塞 UI 线程

转载 作者:太空狗 更新时间:2023-10-29 23:07:10 25 4
gpt4 key购买 nike

我有一个返回数据表的方法。我需要所有的 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 是最好的方法。如前所述,当您等待异步方法时,即使声明的返回类型是 Task ,编译器也会将其转换为 T 的隐式返回类型。

问题是所有异步方法都必须返回 void、Task 或 Task 。因此,一旦开始使用它们,就必须“冒泡”“async”方法属性,直到达到可以阻止结果或者方法可以为 void 或 Task 的程度(即你已经消耗了实际的结果)。

请看这个基于 UI 的简单示例:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
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<string> _ComputeText(bool initialTask)
{
string result = await Task.Run(() =>
{
Thread.Sleep(2000);
return initialTask ? "Task is done!" : "Idle";
});

return result;
}
}

请注意,按钮事件处理程序“Button_Click”被简单地声明为“void”返回。但我可以这样做,因为我在该方法中使用了异步结果。

在您的情况下,返回的 DataTable 在异步任务完成之前不可用。因此,您必须将每个方法声明为“异步”,一直返回到实际对 DataTable 执行某些操作的任何方法。即使在那里,该方法也需要声明为异步,但您不会返回 DataTable,因此该方法可以具有“void”或“Task”的返回类型。一个常见的场景是此方法是一个 UI 事件处理程序,因此“void”在那里应该没问题(并且需要在事件处理程序委托(delegate)中使用);无论如何,您的代码都没有调用它。但从技术上讲,使用“任务”更正确,因此如果在您的上下文中可行,您应该改为使用“任务”。

如果没有简洁但完整的示例,很难提供比这更具体的内容。

关于c# - 从任务返回而不阻塞 UI 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26367548/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com