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

时间:2008-10-31 15:34:27

标签: c# database sql-server-2005 multithreading visual-studio-2005

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

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

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

更好的是警告说“这将返回140,000行数据。你想继续吗?”

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

8 个答案:

答案 0 :(得分:3)

确保优化查询是第一步,但之后,您必须使用线程,并且.NET对这些情况具有BackgroundWorker component

这是complete example

答案 1 :(得分:3)

简单的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
    }

答案 2 :(得分:1)

好的,首先,我建议您尝试更快地进行查询。要检查的第一件事是确保您有适当的索引。网上有大量关于正确使用索引的文章。

如果在所有这些之后,您的查询仍然太慢,则可能必须切换到使用数据库游标。

使用光标,您可以一次读取一个结果,然后拉出它们。这将使您有机会显示进度条。

如果您坚持使用当前的查询模型并只使用线程来绘制进度条,那么您的条形图与正在完成的工作无关,并且看起来不正确。

答案 3 :(得分:1)

我在创建长文件时使用RunWorker和ProgressBar。

我使用的一个技巧是找到代理设置ProgressBar时要使用的文件长度。例如,ProgressBar可能基于函数上次运行时文件中的数字行(可能保存在长文件中)。 ProgressBar或类似的,不一定非精确。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

您可能希望创建另一个表来记录查询的执行时间。这样你就可以说“上次这个过程耗费了X时间。”这将为他们提供一个粗略估计需要多长时间。否则你将不得不运行一个查询以获得一个可能需要很长时间的COUNT。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

对于进度条,请查看Marquee样式。如果由于某种原因获得实际进度报告是不实际的(也就是说,如果使用CURSOR作为dicroce建议结果是站不住脚/太慢/无论如何),您可以使用Marquee进度条显示您的UI仍在响应,你没有忘记用户。

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