如何在后台最好地执行查询以不冻结应用程序(.NET)

时间:2011-05-07 08:30:45

标签: sql multithreading .net-4.0

我的WinForm应用需要执行具有大量执行时间的复杂查询,我没有影响力(大约10分钟) 当查询正在执行时,用户在任务管理器中看到“应用程序没有响应”,这对用户来说真的很混乱,也不是很专业...

我认为查询应该在不同的线程中执行。尝试了一些方法但很难使它真正起作用(执行查询,强制主应用程序等待结果,返回主应用程序,可能取消执行等)

我想知道你是否有自己的/良好的工作解决方案。 代码示例也非常受欢迎:)

此外,我相信可能存在一些准备使用的实用程序/框架,允许简单地执行它。

3 个答案:

答案 0 :(得分:2)

这里最简单的方法是从BackgroundWorker中完成这项工作。 MSDN has examples for this。然后,它在工作线程上执行,包含完成/错误/等事件。它也可以支持取消,但您的操作需要编码为可中断的。

另一种方法是4.0中的Task API;但是如果你使用它,你需要自己回到UI线程(之后)。使用BackgroundWorker,这是自动的(事件在UI线程上引发)。

答案 1 :(得分:1)

如果ExecuteQuery如果您要执行该方法,则可以执行以下操作:

void SomeMethod() {
    var thread = new Thread(ExecuteQuery);
    thread.Start();
}

void ExecuteQuery() {
    //Build your query here and execute it.
}

如果ExecuteQuery收到一些参数,例如:

void ExecuteQuery(string query) {
    //...
}

你可以这样做:

var threadStarter = () => { ExecuteQuery("SELECT * FROM [Table]"); };
var thread = new Thread(ThreadStarter);
thread.Start();

如果要停止执行后台线程,请避免调用thread.Abort()方法。那将是kill线程,你不希望这样,因为你的数据库中可能会出现一些不合适的情况。

相反,您可以从bool看到ExecuteQuery变量,当您想要停止它时,可以从外部将其设置为True。然后,您需要做的就是检查ExecuteQuery中代码的某些部分(如果该变量仍为True)。否则,请执行一些回滚以保持数据库稳定。

请务必设置bool变量volatile

修改
如果您希望UI 从后台线程等待,我通常会这样做:

  • 启动后台主题
  • 在UI中启动一些进度条
  • 禁用某些控件(如按钮等)以避免用户在后台线程工作时单击它们(例如:如果您在用户单击按钮时执行该线程,则你应该禁用该按钮,否则会同时发出多个查询。)

完成线程后,您可以停止进度条并再次启用控件。

如何知道线程何时完成?您可以使用事件。只需创建一个事件并在它完成时触发它,并在事件处理程序中做任何你想做的事情......

确保您正在从后台线程正确访问UI控件,否则会出错。

答案 2 :(得分:0)

如果您是线程新手并且任务很简单(看起来如此),您应该尝试使用standard background worker组件。