首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在WPF中停止一个方法(由单击按钮触发)

如何在WPF中停止一个方法(由单击按钮触发)
EN

Stack Overflow用户
提问于 2021-03-12 19:20:16
回答 1查看 120关注 0票数 1

我在我的WPF中有一个私有的异步void Button_Click方法,它运行一个非常复杂的SQL查询,可以运行几分钟。我希望用户可以通过单击另一个按钮来停止此方法。我的代码是这样的:

代码语言:javascript
运行
复制
public partial class MainWindow : Window  
{
  private async void Button_Click(object sender, RoutedEventArgs e)
  {
     string SQL_Query= " a very long and complicated SQL query ... "
     SqlCommand SQL_Query_cmd = new SqlCommand(SQL_Query, conn);
    
     DataTable dt = new DataTable();
     await Task.Run(() => {
     using (SqlDataAdapter a = new SqlDataAdapter(SQL_Query_cmd))
     { a.Fill(dt);}
     });

  }
}

我在这个How to use WPF Background Worker链接中读到了关于BackgroundWorker的信息。但是不知道如何将它集成到我的代码中。我认为,我的“填充datatable”代码已经是异步的,但我不知道如何停止它。假设要结束此方法的按钮名为stop_btn,其Click方法名为cancelButton_Click

请在帖子中写下你的答案,而不是评论。我会非常感激的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-12 23:40:50

下面是如何使用IDbCommand.Cancel方法和CancellationTokenSource在服务器端和客户端执行取消操作。

代码语言:javascript
运行
复制
private IDbCommand _activeSqlCommand;
private CancellationTokenSource _cts;

private async void btnExecute_Click(object sender, RoutedEventArgs e)
{
    // The _activeSqlCommand and _cts should be null here.
    // Otherwise, you may end up with multiple concurrent executions.
    Debug.Assert(_activeSqlCommand == null);
    Debug.Assert(_cts == null);
    var sqlQuery = "A very long and complicated SQL query...";
    var localSqlCommand = new SqlCommand(sqlQuery, _connection);
    var localCts = new CancellationTokenSource();
    _activeSqlCommand = localSqlCommand;
    _cts = localCts;
    btnExecute.IsEnabled = false;
    btnCancel.IsEnabled = true;
    try
    {
        DataTable dataTable = await AsCancelable(Task.Run(() =>
        {
            var dt = new DataTable();
            using (SqlDataAdapter a = new SqlDataAdapter(localSqlCommand))
                a.Fill(dt);
            return dt;
        }, localCts.Token), localCts.Token);
        // Here use the dataTable to update the UI
    }
    catch (OperationCanceledException) { } // Ignore
    catch (SqlException ex) when (ex.ErrorCode == CANCEL_ERROR_CODE) { } // Ignore
    finally
    {
        btnCancel.IsEnabled = false;
        btnExecute.IsEnabled = true;
        // The _activeSqlCommand and _cts should still have the local values here.
        Debug.Assert(_activeSqlCommand == localSqlCommand);
        Debug.Assert(_cts == localCts);
        _activeSqlCommand = null;
        _cts = null;
        localCts.Dispose();
    }
}

private void btnCancel_Click(object sender, RoutedEventArgs e)
{
    _activeSqlCommand?.Cancel();
    _cts?.Cancel();
}

private static Task<T> AsCancelable<T>(Task<T> task,
    CancellationToken cancellationToken)
{
    var cancelable = new Task<T>(() => default, cancellationToken);
    return Task.WhenAny(task, cancelable).Unwrap();
}

您必须找出在取消执行时数据库服务器抛出的异常类型,并根据其ErrorCode或某些其他属性忽略此异常。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66598956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档