简体   繁体   中英

C# 5 Async Await .Task.Factory.StartNew cancellation

I have the async code that implements cancellation token. It's working but Im not pretty sure if this is the right way to do it so I just want feedback about it.

Here is the actual code:

    /// <summary>
    /// 
    /// </summary>
    private async void SaveData() {

        if (GetActiveServiceRequest() != null)
        {
            var tokenSource = new System.Threading.CancellationTokenSource();


            this.ShowWizardPleaseWait("Saving data...");

            var someTask = System.Threading.Tasks.Task<bool>.Factory.StartNew(() =>
            {

                bool returnVal = false;

                // Set sleep of 7 seconds to test the 5 seconds timeout.
                System.Threading.Thread.Sleep(7000);

                if (!tokenSource.IsCancellationRequested)
                {
                    // if not cancelled then save data

                    App.Data.EmployeeWCF ws = new App.Data.EmployeeWCF ();
                    returnVal = ws.UpdateData(_employee.Data);
                    ws.Dispose();
                }

                return returnVal;

            }, tokenSource.Token);


            if (await System.Threading.Tasks.Task.WhenAny(someTask, System.Threading.Tasks.Task.Delay(5000)) == someTask)
            {
                // Completed
                this.HideWizardPleaseWait();
                if (someTask.Result)
                {
                    this.DialogResult = System.Windows.Forms.DialogResult.OK;
                }
                else
                {
                    this.DialogResult = System.Windows.Forms.DialogResult.Abort;
                }
                btnOK.Enabled = true;
                this.Close();
            }
            else
            {
                tokenSource.Cancel();

                // Timeout logic
                this.HideWizardPleaseWait();
                MessageBox.Show("Timeout. Please try again.")
            }


        }
    }

Does async / await / cancellation code is well implemented?

Thanks and appreciate the feedback.

In general, you should use ThrowIfCancellationRequested . That will complete the returned Task in a canceled state, rather than in a "ran to completion successfully" state with a false result.

Other points:

  • Avoid async void . This should be async Task unless it's an event handler.
  • Prefer Task.Run over TaskFactory.StartNew .
  • Use using .
  • If you're just using CancellationTokenSource as a timeout, then it has special capabilities for that. Creating a separate task via Task.Delay and Task.WhenAny isn't necessary.

Here's what the updated code would look like:

private async Task SaveData()
{
    if (GetActiveServiceRequest() != null)
    {
        var tokenSource = new System.Threading.CancellationTokenSource(TimeSpan.FromSeconds(5));
        var token = tokenSource.Token;

        this.ShowWizardPleaseWait("Saving data...");

        var someTask = System.Threading.Tasks.Task.Run(() =>
        {
            // Set sleep of 7 seconds to test the 5 seconds timeout.
            System.Threading.Thread.Sleep(7000);

            // if not cancelled then save data
            token.ThrowIfCancellationRequested();
            using (App.Data.EmployeeWCF ws = new App.Data.EmployeeWCF())
            {
                return ws.UpdateData(_employee.Data);
            }
        }, token);

        try
        {
            var result = await someTask;

            // Completed
            this.HideWizardPleaseWait();
            if (result)
            {
                this.DialogResult = System.Windows.Forms.DialogResult.OK;
            }
            else
            {
                this.DialogResult = System.Windows.Forms.DialogResult.Abort;
            }
            btnOK.Enabled = true;
            this.Close();
        }
        catch (OperationCanceledException)
        {
            // Timeout logic
            this.HideWizardPleaseWait();
            MessageBox.Show("Timeout. Please try again.")
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM