取消异步任务

时间:2015-07-07 06:38:32

标签: c# .net asynchronous async-await

例如我有类似的东西。当我点击第一个按钮时,它启动了异步过程,然后我点击了第二个按钮,它开始了第二个过程。但点击每个按钮后,我只需要一个进程即可工作。如何取消其他流程?

Worksheets("CalculInfo").Range("BC3").Value = ChoixImage

 image = ChoixImage



    Dim r As Range
Dim ws As Worksheet
Dim imagePath As String
Dim img As Picture

Set ws = Worksheets("PDF")
Set r = ws.Range("R19:U30")

'I got an error here "Impossible to read the image picture propriety insert of the class picture"

Set img = ws.Pictures.Insert(image)



With img
    .ShapeRange.LockAspectRatio = msoFalse
    .Top = r.Top
    .Left = r.Left
    .Width = r.Width
    .Height = r.Height
End With

4 个答案:

答案 0 :(得分:4)

我不确定您希望StartCount中的while条件如何工作,但只要您评估新的CancellationToken就可以取消。记住Thread.Sleep在睡眠时不会取消。所以你最多可能有1秒的延迟。

public void StartCount(int input, CancellationToken token)
{
    SomeData = input;
    while (input > 0 && !token.IsCancellationRequested)
    {
        System.Threading.Thread.Sleep(1000);
        input -= 1;
        SomeData = input;
    }
}

IAsyncResult process;
public void Begin(int input)
{
    if (process != null && !process.IsCompleted)
        ((CancellationTokenSource)process.AsyncState).Cancel();
    Action<int, CancellationToken> Start = new Action<int, CancellationToken>(StartCount);
    var cancelSource = new CancellationTokenSource();
    process = Start.BeginInvoke(input,cancelSource.Token, null, cancelSource);
}

答案 1 :(得分:0)

我会使用Microsoft的Reactive Framework来实现这一点。

这是你的班级:

public class TestCombo : INotifyPropertyChanged
{
    private int someData;
    public int SomeData 
    {
        get { return someData; }
        set { someData = value; RaisePropertyChanged("SomeData"); }
    }

    private SingleAssignmentDisposable _subscription = new SingleAssignmentDisposable();

    public void Begin(int input)
    {
        _subscription.Disposable =
            Observable
                .Interval(TimeSpan.FromSeconds(1.0))
                .Select(x => input - (int)x)
                .Take(input)
                .ObserveOnDispatcher()
                .Subscribe(x => this.SomeData = x);
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged (string info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

此解决方案的两个关键部分是首先执行所有计时的可观察查询订阅,计算要分配给SomeData的值,并将分配编组到UI线程。

第二个是SingleAssignmentDisposable。当您为其IDisposable媒体资源分配新Disposable时,它会处置以前分配的任何IDisposable

处置取消之前的订阅。

Just NuGet&#34; Rx-WPF&#34;获取Rx的WPF位。

答案 2 :(得分:0)

尝试这样的事情:

namespace WpfApplication55
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        TestCombo TC = new TestCombo();
        CancellationTokenSource cts;
        public MainWindow()
        {
            DataContext = TC;
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }

            cts = new CancellationTokenSource();

            await TC.DoAsync(60, cts.Token);
        }

        private void Button_Click1(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }

            cts = new CancellationTokenSource();

            await TC.DoAsync(120, cts.Token);
        }
    }

    public class TestCombo:INotifyPropertyChanged
    {
        private int someData;
        public int SomeData 
        {
            get { return someData; }
            set { someData = value; RaisePropertyChanged("SomeData"); }
        }

        public void StartCount(int input)
        {
            SomeData = input;
            while (input>0)
            {
                System.Threading.Thread.Sleep(1000);
                input -= 1;
                SomeData = input;
            }
        }

        public Task DoAsync(int input, CancellationToken cancellationToken)
        {   
            return Task.Run(StartCount, cancellationToken);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged (string info)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

答案 3 :(得分:-1)

尝试使用类CancellationTokenSource; 请参阅下面的代码 -

CancellationTokenSource   ctstask = new CancellationTokenSource();
ctstask.Cancel();//This line should be called from 2nd button click.