gpt4 book ai didi

c# - 执行后台操作时无法访问 AbortButton

转载 作者:行者123 更新时间:2023-11-30 12:21:33 25 4
gpt4 key购买 nike

我的要求是需要在单击警告框中的中止按钮时中止后台工作程序操作(附图 Export )。因为 GetData() 将花费更多时间来执行。

如果调用 Dowork 方法,则无需访问 UI 元素,这意味着我们需要对其进行限制,直到 backgroundworker 完成。所以我放置了 Application.Current.Dispatcher。如果我删除那行 (Application.current.dispatcher) 我们可以访问 UI 元素并执行一些操作,但我们需要在执行 dowork 事件时限制它。

对此的任何解决方案,

     try
{
var backGroundWorker = new CancelSupportedBackgroundWorker { WorkerSupportsCancellation = true };
CancellationTokenSource source = new CancellationTokenSource();
var alertBox = new AlertBox
{
IsBusy = true,
WaitingText ="Export Data"
WaitingHeaderText ="Exporting"
};
alertBox.AbortButton.Click += (obj, args) =>
{
source.Cancel();
backGroundWorker.CancelAsync();
backGroundWorker.Abort();
backGroundWorker.Dispose();
GC.Collect();
};
backGroundWorker.DoWork += (obj, args) =>
{
Appliction.Current.Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new Action(
delegate
{
table = GetData((CancellationToken)args.Argument);

if (source.Token != default(CancellationToken))
if (source.Token.IsCancellationRequested)
return;
}));
};
backGroundWorker.RunWorkerCompleted += (obj, args) =>
{
alertBox.IsBusy = false;
};
backGroundWorker.RunWorkerAsync(source.Token);
}

提前致谢。

我进行了编辑,将 token 参数传递给 Dowork 事件

明确的要求是:

1) 查询操作需要在后台运行

2) 我们无法访问文件菜单项等其他 UI 元素

3) 执行查询时只访问alertbox中的abort按钮

如果点击中止按钮,它会自动取消后台操作。

我使用 Task.Run() 方法进行了编辑

     Task backgroundTask = null;
try
{

CancellationTokenSource source = new CancellationTokenSource();
var alertBox = new AlertBox
{
IsBusy = true,
WaitingText ="Export Data"
WaitingHeaderText ="Exporting"
};
alertBox.AbortButton.Click += (obj, arg) =>
{
source.Cancel();
GC.Collect();
};
backgroundTask = Task.Run(() => table = GetFullData(source.Token));
IWorkBook.ImportDataTable(table, true, 1, 1, true);
}
catch (ThreadAbortException)
{

}

我做了更改以添加 GetFullData() 方法

 internal DataTable GetFullData(CancellationToken token)
{
DataTable dataTable = new DataTable();


if (connection.State != ConnectionState.Open)
{
connection.Open();
}

var command = connection.CreateCommand();
command.CommandText = query;
if (QueryParameters != null && QueryParameters.Count > 0)
{
foreach (var parameter in QueryParameters)
{
var param = command.CreateParameter();
param.ParameterName = "@" + parameter.Name.TrimStart('@');
if (string.IsNullOrEmpty(parameter.Value))
{
param.Value = DBNull.Value;
}
else
{
param.Value = parameter.Value;
}

command.Parameters.Add(param);
}

command.GetPreparedSql();
}

command.Connection = connection;
if (connection.State != ConnectionState.Open)
{
connection.Open();
}

var reader = command.ExecuteReader();
var dataTable = new DataTable();
if (token != default(CancellationToken))
token.ThrowIfCancellationRequested();
dataTable.Load(reader);
return dataTable;
}

最佳答案

在更详细地查看您的代码后,您似乎不需要 IProgress。

如果你想在另一个线程上调用任何代码,你应该看看它,但只是基于问题,你只需要使用 Task.Run & CancellationToken.

此代码采用名为 frmDoWork 的表单,其中包含 2 个按钮 cmdDoWorkcmdAbort

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsApplication1
{
public partial class frmDoWork : Form
{
CancellationTokenSource cts = null;
Task backgroundTask = null;

public frmDoWork()
{
InitializeComponent();
}

private void WorkToDoInBackgroundThread(IProgress<int> progress, CancellationToken cancellationToken)
{
try
{
for (int i = 0; i < 10; i++)
{
cancellationToken.ThrowIfCancellationRequested();
Task.Delay(1000).Wait(cancellationToken);
progress.Report(i);
System.Diagnostics.Debug.WriteLine($"{i} - {DateTime.Now}");
}
}
catch(OperationCanceledException ex)
{

}

}

private void cmdDoWork_Click(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
Progress <int> prg= new Progress<int>(x => this.Text = $"Iteration - {x}");

backgroundTask = Task.Run(()=> WorkToDoInBackgroundThread(prg, cts.Token));
}

private void cmdAbort_Click(object sender, EventArgs e)
{
cts?.Cancel();
}
}
}

您将需要检查任务是否已在运行,并决定在运行时如何处理(取消或等待)。这实际上只是意味着如果您在任务完成后将其重置为 null,则检查 cts 是否为 null。

您还可以根据需要处理已取消的异常。此代码刚刚退出。

我进行了编辑以展示如何使用 IProgress 接口(interface)对另一个线程进行回调。

这是在显示警告框时禁用所有者表单的代码段。适应您的需求。

{
AlertBox alertBox = new AlertBox();
alertBox.Owner = this;
alertBox.Show();
alertBox.Closed += (sender, e) => this.IsEnabled = true;
this.IsEnabled = false;
}

关于c# - 执行后台操作时无法访问 AbortButton,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45453531/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com