[英]Pause a task when an event is generated
我有一个MS图表控件。 我创建了一个单独的线程以用点填充它,然后绘制每个点,然后让线程休眠一段时间,然后绘制下一个点,以便图形看起来像是在移动。 这是代码。
Task[] t = new Task[1];
t[0] = Task.Factory.StartNew(() => plotChartPoints());
public void plotPoint(int x, double y, int series)
{
comparisonChart.Series[series].Points.AddXY(x, y);
}
public void refreshChart()
{
this.mainSplitContainer.Panel2.Refresh();
}
public void plotChartPoints()
{
//comparisonChart.Series[0].Points.DataBindXY(xValuesSeries1.ToArray(), yValuesSeries1.ToArray());
//comparisonChart.Series[1].Points.DataBindXY(xValuesSeries2.ToArray(), yValuesSeries2.ToArray());
for (int index = 0; index < xValuesSeries1.Count; index++)
{
if (comparisonChart.InvokeRequired)
{
comparisonChart.Invoke(new MethodInvoker(() => plotPoint(xValuesSeries1.ElementAt(index), yValuesSeries1.ElementAt(index), 0)));
comparisonChart.Invoke(new MethodInvoker(() => plotPoint(xValuesSeries2.ElementAt(index), yValuesSeries2.ElementAt(index), 1)));
}
Thread.Sleep(50);
if (this.mainSplitContainer.InvokeRequired)
{
mainSplitContainer.Invoke(new MethodInvoker(()=> refreshChart()));
}
}
}
现在,我想添加一个按钮,以便在单击该按钮时,填充图表的任务暂停,图表冻结。 我该如何完成? 我正在使用.NET 4.0,但是在Task
类中看不到任何暂停Task的方法
当您可以暂停线程时,正在运行的任务会比您已经在使用的Sleep()
还要糟糕。
您应该用WinForms Timer替换所有这些。 这消除了对Invoke()和Sleep()的需要,并且可以轻松停止Timer( Enabled = false;
)。
在Task或线程中没有内置函数可以执行此操作,只有OS Scheduler可以在启动后暂停和恢复线程。 但是一种解决方法可能是使用CancellationToken作为参数
TaskFactory.StartNew<TResult> Method (Func<TResult>, CancellationToken)
单击按钮并将索引的当前值存储在方法范围变量之外,单击恢复后,可以从到达的点开始索引
以下是一个简单的示例,您如何做到这一点
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ChartController _chartController = new ChartController();
public bool paused;
public MainWindow()
{
InitializeComponent();
}
private void PlayPauseButton_OnClick(object sender, RoutedEventArgs e)
{
paused = !paused;
if (!paused)
{
_chartController.CancelAnim();
}
else
_chartController.StartTask();
}
}
public class ChartController
{
private CancellationTokenSource tokenSource = new CancellationTokenSource();
private CancellationToken _cancellationToken;
private int reachedChartIndex = 0;
public void CancelAnim()
{
tokenSource.Cancel();
}
public ChartController()
{
}
public void StartTask()
{
Task t = Task.Factory.StartNew(() => plotChartPoints(), tokenSource.Token);
_cancellationToken = tokenSource.Token;
//to handle exeption if there is
try
{
t.Wait();
}
catch (AggregateException e)
{
foreach (var v in e.InnerExceptions)
//here manage task exception
}
}
public void plotPoint(int x, double y, int series)
{
comparisonChart.Series[series].Points.AddXY(x, y);
}
public void refreshChart()
{
this.mainSplitContainer.Panel2.Refresh();
}
public void plotChartPoints()
{
_cancellationToken.ThrowIfCancellationRequested();
//comparisonChart.Series[0].Points.DataBindXY(xValuesSeries1.ToArray(), yValuesSeries1.ToArray());
//comparisonChart.Series[1].Points.DataBindXY(xValuesSeries2.ToArray(), yValuesSeries2.ToArray());
for (int index = reachedChartIndex; index < xValuesSeries1.Count; index++)
{
if (_cancellationToken.IsCancellationRequested)
{
reachedChartIndex = index;
break;
}
if (comparisonChart.InvokeRequired)
{
comparisonChart.Invoke(
new MethodInvoker(
() => plotPoint(xValuesSeries1.ElementAt(index), yValuesSeries1.ElementAt(index), 0)));
comparisonChart.Invoke(
new MethodInvoker(
() => plotPoint(xValuesSeries2.ElementAt(index), yValuesSeries2.ElementAt(index), 1)));
}
Thread.Sleep(50);
if (this.mainSplitContainer.InvokeRequired)
{
mainSplitContainer.Invoke(new MethodInvoker(() => refreshChart()));
}
}
}
}
}
一种解决方法不是暂停线程,而是基于由UI线程设置和重置的变量(或属性)使用Thread.Sleep。
...
Thread.Sleep(50);//the sleep that you have in your code
while (paused)
{
Thread.Sleep(100);
}
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.