C# 如何停止无止境循环的任务

C# 如何停止无止境循环的任务,c#,multithreading,button,task,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

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

如何使用停止按钮停止任务(无止境循环)

我的解决方案不起作用,使用开始按钮后用户界面冻结。因此,我认为我可以用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); 
                            }));
                    }
                }
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
名称空间WpfApp5_任务和Darstellu测试
{
/// 
///Interaktionslogik für MainWindow.xaml
/// 
公共部分类主窗口:窗口
{
私人停车场;
传输tr=新传输();
公共主窗口()
{
初始化组件();
}
私有无效列表视图1\u选择已更改(对象发送方,
选择ChangedEventArgs(e)
{
}
私有无效开始按钮单击(对象发送者,路由目标)
{
停止=错误;
ObservableCollection数据=新的ObservableCollection();
做
{
新任务(()=>{tr.GetData(Data);}).Start();
}while(stop!=true);
listView1.ItemsSource=数据;
}
公共作废停止按钮\单击(对象发送者,路由目标)
{
停止=真;
}
}
公共类转移
{
public void GetData(ObservableCollectiondata)
{
while(true)
{
对于(int i=0;i<2;i++)
{
对于(int j=0;j<3;j++)
{
int d=i+j;
Application.Current.Dispatcher.Invoke(
新操作(()=>
{
数据.添加(d);
}));
}
}
}
}
}
}

我还不明白这件事是否真的发生了改变。谢谢大家

创建一个新函数,将开始按钮中的内容放入该函数,单击该函数,然后设置一个线程来执行该函数。通过这种方式,主线程可以使UI保持活动状态,而后台的线程可以完成此工作。

创建一个新函数,在开始按钮中放入内容\u单击该函数,然后设置一个线程来执行该函数。通过这种方式,您的主线程可以使UI保持活动状态,后台的线程可以执行此操作。

首先,我们将使用为GetData方法添加取消支持,否则您无法真正取消此操作(您可以停止等待,但操作仍将继续,并继续向集合中添加项目,我们为什么要这样做?)

公共类传输
{
public void GetData(ObservableCollectiondata、CancellationToken CancellationToken)
{
while(true)
{
对于(int i=0;i<2;i++)
{
对于(int j=0;j<3;j++)
{
//如果要求取消操作,将抛出OperationCanceledException
cancellationToken.ThrowIfCancellationRequested();
数据.添加(d);
}
}
}
}
}
请注意,此处不需要使用Dispacher,因为此时集合未绑定到UI。

然后我们可以使用取消主窗口中的操作,并在单击开始按钮时防止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();
    }
}
公共部分类主窗口:窗口
{
私有传输_传输=新传输();
私有CancellationTokenSource _CancellationTokenSource=新的CancellationTokenSource();
公共主窗口()
{
初始化组件();
}
私有异步无效开始按钮单击(对象发送方,路由目标)
{
ObservableCollection数据=新的ObservableCollection();
尝试
{
等待任务。运行(()=>_transfer.GetData(Data,_cancellationTokenSource.Token);)
listView1.ItemsSource=数据;
}
捕捉(操作取消例外)
{
MessageBox.Show(“取消”);
}
}
私有无效停止按钮\单击(对象发送者,路由目标)
{
_cancellationTokenSource.Cancel();
}
}

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

首先,我们将使用向GetData方法添加取消支持,否则您无法真正取消该操作(您可以停止等待,但该操作仍将继续并继续向集合中添加项,我们为什么要这样做?)

公共类传输
{
public void GetData(ObservableCollectiondata、CancellationToken CancellationToken)
{
while(true)
{
对于(int i=0;i<2;i++)
{
对于(int j=0;j<3;j++)
{
//如果要求取消操作,将抛出OperationCanceledException
cancellationToken.ThrowIfCancellationRequested();
数据.添加(d);
}
}
}
}
}
请注意,此处不需要使用Dispacher,因为此时集合未绑定到UI。

然后我们可以使用取消主窗口中的操作,并在单击开始按钮时防止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();
    }
}
公共部分类主窗口:窗口
{
私有传输_传输=新传输();
私有CancellationTokenSource _CancellationTokenSource=新的CancellationTokenSource();
公共M