【问题标题】:C# 5 Async Await .Task.Factory.StartNew cancellationC# 5 Async Await .Task.Factory.StartNew 取消
【发布时间】:2021-01-09 20:30:56
【问题描述】:

我有实现取消令牌的异步代码。它正在工作,但我不太确定这是否是正确的方法,所以我只是想要关于它的反馈。

下面是实际代码:

    /// <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.")
            }


        }
    }

async/await/cancel 代码是否实现得很好?

感谢并感谢您的反馈。

【问题讨论】:

  • 太棒了!感谢您的提示

标签: c# task-parallel-library async-await


【解决方案1】:

一般来说,您应该使用ThrowIfCancellationRequested。这将使返回的Task 以取消状态完成,而不是在“成功运行到完成”状态并产生false 结果。

其他要点:

  • 避免async void。这应该是async Task,除非它是一个事件处理程序。
  • Prefer Task.Run over TaskFactory.StartNew
  • 使用using
  • 如果您只是使用CancellationTokenSource 作为超时,那么它具有特殊功能。无需通过Task.DelayTask.WhenAny 创建单独的任务。

更新后的代码如下所示:

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.")
        }
    }
}

【讨论】:

  • 惊人的回复!!!非常感谢您的帮助斯蒂芬...非常清楚和非常专业的答复!!!
  • 当我调用 SaveData() 并将其悬停时,它显示: 用法:await SaveData();警告:因为这个调用它没有等待.....这样可以吗?
  • 可能不会。最有可能的是,您应该 await 它。
猜你喜欢
  • 1970-01-01
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 2013-06-04
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多