How to show loading dialog while a long time query

2019-08-09 05:24发布

I created a winforms app with .net 4.0.

First, I created a LoadingForm with cancel button, that must stop execution query.

I want to create an ExecuteHelper class and LoadingForm with cancellation query button.

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();
    }
}

Then, I create an ExecuteHelper class:

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);
    }
}

Something is wrong, and it does not show the desired effect. Can anybody help?

Maybe this solution is right:

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() blocked the main thread and I can't click on button in loading form for cancel query execution.

0条回答
登录 后发表回答