取消异步任务
本文关键字:任务 异步 取消 | 更新日期: 2023-09-27 18:01:15
例如:当我点击第一个按钮,它开始的异步进程,然后我点击第二个按钮,它开始的第二个进程。但我只需要一个过程后,点击每个按钮工作。我如何取消其他进程?
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,你应该很好地取消。记住线程。睡眠在它睡觉的时候不会取消。所以你可能有最多15秒的延迟。
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);
}
我会使用微软的响应式框架。
这是你的类:
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
。
处置取消先前的订阅。
只需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.