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