我使用.net 4.0创建了一个winforms应用程序。
首先,我创建了一个带取消按钮的LoadingForm,它必须停止执行查询。
我想使用取消查询按钮创建ExecuteHelper
班级和LoadingForm
。
public partial class LoadingFrm : DevExpress.XtraEditors.XtraForm
{
private Action _cancel;
public LoadingFrm(Action a)
{
_cancel = a;
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
}
private void simpleButton1_Click(object sender, EventArgs e)
{
this.close();
_cancel();
}
}
然后,我创建了一个ExecuteHelper
类:
public class ExecuteHelper
{
private readonly int tOut = 1000;
private LoadingFrm _loadFrm;
private SqlDataReader _result;
private Task worker;
private CancellationTokenSource cts;
private IAsyncResult iAr;
private SqlCommand _command;
ExecuteHelper()
{
_loadFrm = new LoadingFrm(CancelExecution);
}
public SqlDataReader Execute(SqlCommand command)
{
_command = command;
cts = new CancellationTokenSource();
var cToken = cts.Token;
cts.Token.Register(() => _loadFrm.Invoke((MethodInvoker)delegate() { _loadFrm.Close(); }));
worker = new Task(() => { _loadFrm.ShowDialog(); }, cToken);
SqlDataReader r = null;
worker.Start();
iAr = command.BeginExecuteReader();
while (!iAr.IsCompleted)
{
}
r = command.EndExecuteReader(iAr);
cts.Cancel();
return r;
}
public void CancelExecution()
{
_command.EndExecuteReader(iAr);
}
}
出了点问题,并没有显示出预期效果。有人可以帮忙吗?
也许这个解决方案是正确的:
public static SqlDataReader Execute(SqlCommand command)
{
var cts = new CancellationTokenSource();
var cToken = cts.Token;
cToken.Register(() => { command.Cancel(); });
Task<SqlDataReader> query = new Task<SqlDataReader>(new Func<SqlDataReader>(() => { return command.ExecuteReader(); }), cToken);
LoadingFrm _loadingF = new LoadingFrm(() => { cts.Cancel(); });
new Action(() => { _loadingF.Show(); }).Invoke();
query.Start();
query.Wait(30000, cToken);
query.ContinueWith((obj) =>
{
_loadingF.Invoke((MethodInvoker)delegate
{
_loadingF.Close();
});
});
return query.Result;
}
Bur query.start()
阻止了主线程,我无法点击加载表单中的按钮来执行取消查询。