C# 什么是正确的方法来处理需要;“长时间”;完成?
我在VisualStudio2005Pro中创建了一个Winforms应用程序,它使用SqlConnection/SqlCommand/SqlDataAdapter类连接到SQLServer2005数据库以提取数据。我的数据库中有存储过程来将数据返回给我 处理需要“很长时间”才能完成的查询的最佳方法是什么?(即,足够长的时间,用户开始认为有问题)。当前,我的应用程序将锁定,直到查询完成或查询超时。显然,这是不可接受的 我至少想要一个有“停止”按钮的进度表。进度表甚至不需要做任何有用的事情,作为一个耐心等待的提示就足够了 更好的警告是这样的:“这将返回140000行数据。是否继续?”C# 什么是正确的方法来处理需要;“长时间”;完成?,c#,database,sql-server-2005,multithreading,visual-studio-2005,C#,Database,Sql Server 2005,Multithreading,Visual Studio 2005,我在VisualStudio2005Pro中创建了一个Winforms应用程序,它使用SqlConnection/SqlCommand/SqlDataAdapter类连接到SQLServer2005数据库以提取数据。我的数据库中有存储过程来将数据返回给我 处理需要“很长时间”才能完成的查询的最佳方法是什么?(即,足够长的时间,用户开始认为有问题)。当前,我的应用程序将锁定,直到查询完成或查询超时。显然,这是不可接受的 我至少想要一个有“停止”按钮的进度表。进度表甚至不需要做任何有用的事情,作为一
我知道这可能需要线程,但如何实现?要实现您的警告,您可以首先发出COUNT()查询,该查询不仅会返回用户将要获取的行数,而且可能会开始缓存数据。您可能需要创建另一个表来记录查询的执行时间。这样你可以说“上一次这个过程花费了X个时间。”这将为他们提供一个大概的估计时间。否则,您必须运行查询才能获得一个可能需要较长时间的计数。好,首先,我建议尝试使查询更快。首先要检查的是确保您有适当的索引。网上有大量关于正确使用索引的文章 如果在所有这些之后,您的查询仍然太慢,那么您可能必须切换到使用数据库游标 使用光标,您可以一次读取一个结果,然后拖动它们。这将使您有机会显示进度条
如果您坚持当前的查询模型,仅使用线程绘制进度条,则进度条与正在完成的工作无关,看起来也不正确。您将希望利用线程。当用户发出获取数据的信号时,您可以生成一个新线程来获取数据,同时在主窗体上显示一个throbber。当线程返回时,您可以做出反应并显示结果 确保查询得到优化是第一步,但之后,您必须使用线程,而.NET有针对这些情况的解决方案 下面是一个简单的C#2.0示例:
private void Form_Load(object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
//change UI to reflect we're doing this
bw.RunWorkerAsync();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
//SQL Work
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Let the user know we're done
}
我在创建长文件时使用RunWorker和ProgressBar
我使用的一个技巧是在设置ProgressBar时找到一个与文件长度相同的代理。例如,ProgressBar可能基于上次运行函数时文件中的行数(可能保存在长文件中)。进度条或类似的进度条不一定要精确。对于进度条,请查看选框样式。如果由于某种原因无法获取实际进度报告(也就是说,如果按照dicroce建议的方式使用游标不可行/太慢/不管怎样),您可以使用字幕进度条显示您的UI仍在响应,并且您没有忘记用户
记住Jakob Nielsen的规则:如果你需要超过250毫秒(?)才能返回给用户,他们会担心出了什么问题。通常,您的按钮应该运行任何必要的验证(快速!),然后显示一些告诉用户“我正在工作”的内容,并将控制返回到UI循环。另一方面,计数可能需要很长时间,并且需要自己的进度条!没错。。。但这是一个想法:)