繁体   English   中英

处理需要“很长时间”才能完成的程序的正确方法是什么?

[英]What is the correct way to deal with procedures that take a “long time” to complete?

我有一个在Visual Studio 2005 Pro中创建的Winforms应用程序,它使用SqlConnection / SqlCommand / SqlDataAdapter类连接到SQL Server 2005数据库以提取数据。 我在数据库中存储了过程,以将数据返回给我。

处理需要“很长时间”才能完成的查询的最佳方法是什么? (即足够长的时间,使用户开始认为有问题)。 当前,我的应用程序将锁定,直到查询完成或查询超时。 显然,这是不可接受的。

我至少想要一个带有“停止”按钮的进度表。 进度表甚至不需要做任何有用的事情,暗示耐心地坐着等待就足够了。

更好的是一条警告,上面写着“这将返回140,000行数据。您要继续吗?”这样的警告。

我知道这可能需要线程,但是如何?

确保查询被优化是第一步,但此后,您必须使用线程,.NET在这些情况下具有BackgroundWorker组件

这是一个完整的例子

简单的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可能基于上次运行该函数时文件中的数字行(也许保存在长文件中)。 ProgressBar或类似的对象不必精确。

要实施警告,您可以首先发出COUNT()查询,该查询不仅会返回用户将要获得的行数,而且可能会开始缓存数据。

您可能需要创建另一个表来记录查询的执行时间。 这样,您可以说“上次此过程花费了X倍的时间”。 这将为他们提供大概需要多长时间的估计。 否则,您将必须运行查询以获取COUNT,而这本身可能会花费很长时间。

您将要利用线程。 当用户发出信号来获取数据时,您可以生成一个新线程来获取数据,同时在主窗体上显示一个跳动。 当线程返回时,您可以做出反应并显示结果。

对于进度条,请查看“字幕”样式。 如果由于某种原因而无法获得实际的进度报告(也就是说,如果建议使用CURSOR作为dicroce证明是站不住脚的/太慢了/不管如何),则可以使用Marquee进度条来显示您的UI仍在响应,您并没有忘记该用户。

请记住Jakob Nielsen的规则:如果您花费超过250毫秒(?)返回给用户,他们将担心出现问题。 通常,您的按钮应该运行需要进行的任何验证(快速!),然后显示告诉用户“我正在工作”的内容并将控件返回到UI循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM