c# – 执行后台操作时无法访问AbortButton
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 执行后台操作时无法访问AbortButton,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4543字,纯文字阅读大概需要7分钟。
内容图文
![c# – 执行后台操作时无法访问AbortButton](/upload/InfoBanner/zyjiaocheng/781/a376a76028d94c9d8fb1ab557b839cfb.jpg)
我的要求是需要在alertbox中点击中止按钮时中止后台工作操作(附图像Export).因为GetData()将花费更多时间来执行.
如果调用Dowork方法,则不需要访问UI元素,这意味着我们需要限制它直到后台工作者完成.所以我放了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);
}
提前致谢.
我做了一个编辑,将一个令牌参数传递给Dowork事件
明确要求是:
1)查询操作需要在后台运行
2)我们无法访问其他UI元素,如文件菜单项
3)执行查询时,仅访问alertbox中的中止按钮
如果单击中止按钮,它将自动取消后台操作.
我使用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个按钮cmdDoWork和cmdAbort
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();
}
}
}
您需要检查任务是否已在运行&决定做什么(取消或等待).这实际上只是意味着如果在完成任务后将cts重置为null,则检查cts是否为null.
您也可以根据需要处理已取消的异常.这段代码就退出了.
我做了一个编辑,还展示了如何使用IProgress接口对另一个线程进行回调.
这是一个在显示警告框时禁用所有者表单的代码段.适应您的需求.
{
AlertBox alertBox = new AlertBox();
alertBox.Owner = this;
alertBox.Show();
alertBox.Closed += (sender, e) => this.IsEnabled = true;
this.IsEnabled = false;
}
内容总结
以上是互联网集市为您收集整理的c# – 执行后台操作时无法访问AbortButton全部内容,希望文章能够帮你解决c# – 执行后台操作时无法访问AbortButton所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。