[英]Cancel an async task
例如,我有這樣的事情。 當我單擊第一個按鈕時,它開始異步過程,然后單擊第二個按鈕,它開始第二個過程。 但是單擊每個按鈕后,我只需要一個過程即可工作。 如何取消其他程序?
namespace WpfApplication55
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
TestCombo TC = new TestCombo();
public MainWindow()
{
DataContext = TC;
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
TC.Begin(60);
}
private void Button_Click1(object sender, RoutedEventArgs e)
{
TC.Begin(120);
}
}
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 void Begin(int input)
{
Action<int> Start = new Action<int>(StartCount);
IAsyncResult result = Start.BeginInvoke(input, null, null);
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged (string info)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
我不確定您希望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);
}
我將為此使用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
的值並SomeData
送給UI線程的分配。
第二個是SingleAssignmentDisposable
。 當將新的IDisposable
分配給其Disposable
屬性時,它將處置以前分配的任何IDisposable
。
配置將取消先前的訂閱。
只需NuGet“ Rx-WPF”即可獲得Rx的WPF位。
嘗試這樣的事情:
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));
}
}
}
嘗試使用類CancellationTokenSource; 請參閱下面的代碼-
CancellationTokenSource ctstask = new CancellationTokenSource();
ctstask.Cancel();//This line should be called from 2nd button click.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.