如何通过无限循环停止任务

时间:2017-04-28 14:00:49

标签: c# multithreading button task

实际上这是一个非常简单的问题。

如何使用停止按钮停止我的任务(无限循环)?

我的解决方案不起作用,用户界面在我使用开始按钮后被冻结。因此,我认为我可以使用bool stop变量

来解决它

我的代码:

    using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp5_Task_und_darstellun_test
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool stop;
        Transfer tr = new Transfer();
        public MainWindow()
        {
            InitializeComponent(); 
        }
        private void listView1_SelectionChanged(object sender,
        SelectionChangedEventArgs e)
        {
        }
        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            stop = false;
            ObservableCollection<int> Data = new ObservableCollection<int>();
            do
            {
                new Task(() => { tr.GetData(Data); }).Start();
            } while (stop != true);

            listView1.ItemsSource = Data;
        }

        public void StopButton_Click(object sender, RoutedEventArgs e)
        {
            stop = true;
        }
    }
    public class Transfer
    {
        public void GetData(ObservableCollection<int>data)
        {
            while (true)
            {
                for (int i = 0; i < 2; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        int d = i + j;
                        Application.Current.Dispatcher.Invoke(
                            new Action(() =>
                            {
                                data.Add(d); 
                            }));
                    }
                }
            }
        }
    }
}

我还没有理解INotifyPropertyChanged的问题。非常感谢你们。

2 个答案:

答案 0 :(得分:1)

首先我们将使用CacellationToken为GetData方法添加取消支持,否则你无法真正取消操作(你可以停止等待它,但操作仍会计算并继续向集合中添加项目为什么我们想要那个?)

public class Transfer
{
    public void GetData(ObservableCollection<int>data, CancellationToken cancellationToken)
    {
        while (true)
        {
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    //Will throw OperationCanceledException if the operation was asked to be canceled
                    cancellationToken.ThrowIfCancellationRequested();
                    data.Add(d);
                }
            }
        }
    }
}

请注意,我们不需要在此处使用Dispacher,因为此时集合不受UI限制。

然后我们可以使用CancellatonTokenSourceasync and await取消主窗口中的操作,以防止UI在我们点击开始按钮时冻结:

public partial class MainWindow : Window
{
    private Transfer _transfer = new Transfer();

    private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource ();

    public MainWindow()
    {
        InitializeComponent(); 
    }

    private async void StartButton_Click(object sender, RoutedEventArgs e)
    {
        ObservableCollection<int> Data = new ObservableCollection<int>();
        try
        {
            await Task.Run(() => _transfer.GetData(Data, _cancellationTokenSource.Token);)
            listView1.ItemsSource = Data;
        }
        catch(OperationCanceledException ex)
        {
            MessageBox.Show("Canceled");
        }
    }

    private void StopButton_Click(object sender, RoutedEventArgs e)
    {
        _cancellationTokenSource.Cancel();
    }
}

您可以在MSDN中找到有关“任务取消”的更多信息。

答案 1 :(得分:0)

创建一个新函数,在该函数的StartButton_Click中放置什么,然后设置一个线程来执行该函数。通过这种方式,您的主线程可以保持UI的活动,并且后台的线程可以正常工作。