C# 生成事件时暂停任务
我有一个MS图表控件。我创建一个单独的线程,用点填充它,在绘制每个点之后,我让线程休眠一段时间,然后绘制下一个点,这样图形看起来就像它在移动。 这是代码C# 生成事件时暂停任务,c#,multithreading,.net-4.0,task-parallel-library,C#,Multithreading,.net 4.0,Task Parallel Library,我有一个MS图表控件。我创建一个单独的线程,用点填充它,在绘制每个点之后,我让线程休眠一段时间,然后绘制下一个点,这样图形看起来就像它在移动。 这是代码 Task[] t = new Task[1]; t[0] = Task.Factory.StartNew(() => plotChartPoints()); public void plotPoint(int x, double y, int series) { comparisonChart.Seri
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()));
}
}
}
Task[]t=新任务[1];
t[0]=Task.Factory.StartNew(()=>plotChartPoints());
公共无效绘图点(整数x、双y、整数系列)
{
comparisonChart.Series[Series].Points.AddXY(x,y);
}
公共图表()
{
this.mainSplitContainer.Panel2.Refresh();
}
公共点()
{
//comparisonChart.Series[0].Points.DataBindXY(xValuesSeries1.ToArray(),yValuesSeries1.ToArray());
//comparisonChart.Series[1].Points.DataBindXY(xValuesSeries2.ToArray(),yValuesSeries2.ToArray());
对于(int index=0;indexplotPoint(xValuesSeries1.ElementAt(索引),yValuesSeries1.ElementAt(索引),0));
比较nchart.Invoke(新方法调用程序(()=>plotPoint(xValuesSeries2.ElementAt(索引),yValuesSeries2.ElementAt(索引,1));
}
睡眠(50);
if(this.mainSplitContainer.invokererequired)
{
调用(新的MethodInvoker(()=>refreshChart());
}
}
}
现在,我想添加一个按钮,以便在单击该按钮时,填充图表的任务暂停,图表冻结。
我如何做到这一点?我使用的是.NET 4.0,在
任务
类中没有看到任何暂停任务的方法,而您可以暂停正在运行任务的线程,这将比您已经使用的Sleep()
更糟糕
您应该用WinForms计时器替换所有这些。这样就不需要Invoke()和Sleep(),计时器也可以轻松停止(
Enabled=false;
)。在任务或线程中没有内置函数来完成此操作,只有OS调度器可以在启动后暂停和恢复线程。但一种解决方法可能是使用CancellationToken作为参数
TaskFactory.StartNew<TResult> Method (Func<TResult>, CancellationToken)
TaskFactory.StartNew方法(Func,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()));
}
}
}
}
}
//
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
私有ChartController_ChartController=新ChartController();
公共广播暂停;
公共主窗口()
{
初始化组件();
}
私有void PlayPauseButton_OnClick(对象发送器,RoutedEventArgs e)
{
暂停=!暂停;
如果(!暂停)
{
_chartController.CancelAnim();
}
其他的
_chartController.StartTask();
}
}
公共类图表控制器
{
private CancellationTokenSource tokenSource=新的CancellationTokenSource();
私有取消令牌\u取消令牌;
私有int达到ChartIndex=0;
公共无效取消动画()
{
tokenSource.Cancel();
}
公共财务总监()
{
}
公共无效StartTask()
{
Task t=Task.Factory.StartNew(()=>plotChartPoints(),tokenSource.Token);
_cancellationToken=tokenSource.Token;
//如果有,处理例外情况
尝试
{
t、 等待();
}
捕获(聚合异常e)
{
foreach(e.InnerExceptions中的var v)
//这里管理任务异常
}
}
公共无效绘图点(整数x、双y、整数系列)
{
comparisonChart.Series[Series].Points.AddXY(x,y);
}
公共图表()
{
this.mainSplitContainer.Panel2.Refresh();
}
公共点()
{
_cancellationToken.ThrowIfCancellationRequested();
//comparisonChart.Series[0].Points.DataBindXY(xValuesSeries1.ToArray(),yValuesSeries1.ToArray());
//comparisonChart.Series[1].Points.DataBindXY(xValuesSeries2.ToArray(),yValuesSeries2.ToArray());
对于(int index=reachedChartIndex;index绘图点(xValuesSeries1.ElementAt(索引),yValuesSeries1.ElementAt(索引),0));
comparisonChart.Invoke(
新MethodInvoker(
()=>绘图点(xValuesSeries2.ElementAt(索引),yValuesSeries2.ElementAt(索引,1));
}
睡眠(50);
if(this.mainSplitContainer.invokererequired)
{
调用(新的MethodInvoker(()=>refreshChart());
}
}
}
}
}
您是否可以使用自动重置事件
然后单击按钮,可以发出暂停打印的信号。我假设再次单击按钮时,您将执行“取消暂停”操作
要获得更多控制,请查看手册ResetEventSlim一个解决方法不是暂停线程,而是使用thread.Sleep
...
Thread.Sleep(50);//the sleep that you have in your code
while (paused)
{
Thread.Sleep(100);
}
...