CancellationToken的任务状态不会更改

时间:2014-08-26 01:52:47

标签: c# winforms task cancellation cancellationtokensource

我正在实现一个下载程序类,我正在使用任务,首先我创建了一个任务并用它传递了CancellationToken,当我取消任务时,任务被取消但任务的状态仍在运行,即使在我之后调用ThrowIfCancellationRequested()staus仍然是相同的。如果我抛出ThrowIfCancellationRequested(),请问状态是否为Canceled或Faulted。

这是我的代码:

    public void Start()
    {
        //Start download
        Status = DownloadStatus.Running;
        CancellTS = new CancellationTokenSource();
        CancelT = CancellTS.Token;
        TaskStartDownload = Task.Run(() => { StartDownload(); }, CancelT);
    }

   private void StartDownload()
    {
        //Raise event download start
        if (OnDownloadStart != null)
            OnDownloadStart(this, new DownloadEventArgs(Id, 0, 0, 0, Controls, false));

        byte[] buffer = new byte[4096];
        long bytesToRead = Size;

        Timer.Start();
        while (!CancelT.IsCancellationRequested)
        {
            int currentBytesRead = Reader.Read(buffer, 0, buffer.Length);

            Speed = currentBytesRead == 0 ? 0 : ((float)BytesRead / 1024) / Timer.Elapsed.TotalSeconds;
            ProgressPercentage = ProgressPercentage + (currentBytesRead * 1.0 / Size) * 100;
            TimeRemaining = (int)(((double)(Size - BytesRead) / 1024) / Speed);

            if (currentBytesRead == 0)
            {
                Status = DownloadStatus.Completed;

                //Raise event download start
                if (OnDownloadComplete != null)
                    OnDownloadComplete(this, new DownloadEventArgs(Id, 100, 0, 0, Controls, false));

                break;
            }

            Writer.Write(buffer, 0, currentBytesRead);
            Writer.Flush();

            //Raise progress event
            this.OnDownloadProgress(this, new DownloadEventArgs(Id, Speed, ProgressPercentage, TimeRemaining, Controls, false));

            BytesRead += currentBytesRead;

            if (Status == DownloadStatus.Pause || Status == DownloadStatus.Cancel)
                break;
        }
        Timer.Stop();

        Reader.Close();
        Reader = null;
        Writer.Close();

        if (CancelT.IsCancellationRequested)
        {
            try
            {
                CancelT.ThrowIfCancellationRequested();
            }
            catch (Exception ex)
            {
                Status = DownloadStatus.Cancel;

                //Raise event download start
                if (OnDownloadCancel != null)
                    this.OnDownloadCancel(this, new DownloadEventArgs(Id, 0, 0, 0, Controls, true));

                File.Delete(FileNameWithPath);
            }
        }

        TaskPrepareDownload.Dispose();
        TaskStartDownload.Dispose();
    }

        public void Cancel()
    {
        if (TaskStartDownload == null)
        {
            return;
        }
        else
        {
            CancellTS.Cancel();
        }
    }

1 个答案:

答案 0 :(得分:3)

调用ThrowIfCancellationRequested()后,不应该吞下异常,因此可以通知调用者(Start()方法)任务状态的变化。如果您吞下该异常,则认为该任务已成功完成(Status = RanToCompletion),或者如果您在触发取消后立即轮询该任务,则该任务仍在运行。

当您等待任务完成时,异常处理程序应放在调用者中。

请参阅MSDN Task Cancellation中的示例。