繁体   English   中英

生成事件时暂停任务

[英]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()));
                }

            }
        }

    }

}

您是否可以使用AutoResetEvent MSDN

然后在您的按钮上单击,您可以指示绘图暂停。 我假设再次单击该按钮时,您将执行“取消暂停”操作。

有关更多控制,请查看ManualResetEventSlim MSDN。

一种解决方法不是暂停线程,而是基于由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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM