中止正在运行长查询的线程

时间:2015-06-06 06:36:10

标签: c# wpf multithreading abort

我有一个调用其中一个方法的线程,现在这个方法执行一个查询,可能需要很长时间才能完成40分钟左右,

我想让用户可以选择取消此操作(意味着停止线程并停止查询以释放数据库)。

我应该提一下,我正在使用.net 4.5,SQL SERVER DB和C#开发WPF应用程序。

5 个答案:

答案 0 :(得分:4)

你应该使用backgroundworker,这正是你想要的。

Eather从工具箱中拖放它或在代码后面创建它。它支持取消,报告进度,完成时通知并知道它是否正在运行。

这是一个例子。

void method(){
        BackgroundWorker worker = new BackgroundWorker();
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.DoWork += worker_DoWork;
        worker.WorkerSupportsCancellation = true;
        if(!worker.IsBusy)
        {
            worker.RunWorkerAsync();
        }
}

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //do whatever needs to be done on the other thread here.
        object argument = e.Argument; //if passed argument in RunWorkerAsync().
        object result = new object();
        e.Result = result;
        //after making worker global, you can report progress like so:
        worker.ReportProgress(50); //you can also pass a userState, which can be any object, to show some data already.
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        //you can update a progress bar in here
        int progress = e.ProgressPercentage;

    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //when done
    }

    void CancelTheTask()
    {
        if (worker.IsBusy)
        {
            //make worker global first, but then
            worker.CancelAsync();
        }
    }

要注意的重要事项:切勿在{{1​​}}方法中使用未在其中创建的资源。因此,在后台worker中将您需要的东西作为Arguments传递。而且背景工作者创建的东西不应该设置为全局变量ether,传递结果。

取消时,DoWork也会被解雇。现在,对数据库的查询已经在执行,因此即使您的应用程序丢失了所有资源,它仍然在运行。

要取消它,我们需要知道你如何执行查询,就像提到的@S.Akbari是一种方式。实体框架6还支持取消。

为此:check this when using Queryable

here is another example

或者没有实体框架的solution

答案 1 :(得分:2)

使用Task Parallel Library (TPL),您可以使用Task Cancellation模式。

答案 2 :(得分:2)

当您在等待查询时阻止线程时,它对于停止任何操作都没用。

确保可以从UI访问查询的SqlConnection并关闭它。放弃线程,它将终止(有一个错误,你必须压制)。

答案 3 :(得分:1)

如果UI线程正在进行长时间操作,则无法进行处理 UI请求。这也称为无响应。 像这样使用ThreadPool

CancellationTokenSource ct;//instantiate it before ThreadPool.QueueUserWorkItem line
private void operation_Click(object sender, RoutedEventArgs e)
{
   ct = new CancellationTokenSource();
   ThreadPool.QueueUserWorkItem(_ =>

        {
          var result = LongTimeOperation();//set the operation in another thread so that the UI thread is kept responding
          //use the Dispatcher to "return" to the UI thread
          Dispatcher.BeginInvoke(new Action(() =>
          {
             //Use result for example : Label1.Text = result.ToString();
          }));
        });
}

要让用户选择能够取消操作,请使用CancellationTokenSource,如下所示:

private void cancel_Click(object sender, RoutedEventArgs e)
{
     if (ct != null)
      {
         ct.Cancel();
         ct= null;
      } 
 }

注意:LongTimeOperation()中,您必须再添加一个类型为CancellationToken的参数

private float LongTimeOperation(CancellationToken ct)
{
   if (ct.IsCancellationRequested)
     return -1;
    ....
    ....
}

link对于托管主题中的Cancellation非常有用。

答案 4 :(得分:-1)

这是一个常见问题。但在WPFWinForm中,我想使用BackGroundWorker。见Here