C# 中止线程:此平台不支持线程中止

C# Aborting a thread: Thread abort is not supported on this platform

问题

我在 c# (on windows 10 中创建了一个线程,它向服务器请求一些数据:

这样做是为了让我们节省资源防止错误 如果线程没有关闭就会发生错误。 (请看下面的代码)

我尝试使用 threadName.Abort(),但出现以下错误:

System.PlatformNotSupportedException: 'Thread abort is not supported on this platform.'

我也试过 threadName.Interrupt() 产生了这个错误(错误发生在行:Thread.Sleep(3000);):

System.Threading.ThreadInterruptedException: 'Thread was interrupted from a waiting state.'

这里有什么问题,如何关闭线程?


研究完成

网上查了一下showed没有什么好方法可以中止一个线程,是这样吗?

我还找到了 this 使用 Thread.sleep() 的答案(第一个),但这似乎不是真正的解决方案,因为它不会释放线程的资源,而且我不确定如何在我的代码中实现这个解决方案。


代码

namespace TriviaClient
{
    public partial class MainWindow : Window
    {
        public const int GET_ROOMS_REQUEST = 92;

        public Thread refreshRoomsListThread;

        public static NetworkStream clientStream;

        public MainWindow()
        {
            StartClient();
            InitializeComponent();
        }

        public void refreshRoomList()
        {
            while (true)
            {
                this.Dispatcher.Invoke((Action)(() =>
                {
                    roomsListErrorBox.Text = "";
                }));
                serializeAndSendMessage(GET_ROOMS_REQUEST, "");
                Dictionary<string, object> response = receiveAndDeserializeMessage();

                if (response.ContainsKey("status") && (string)response["status"] == "1")
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {
                        roomsList.Items.Clear();
                    }));

                    Dictionary<int, string> rooms = new Dictionary<int, string>();

                    JArray Jrooms = (JArray)response["rooms"];


                    foreach (JArray room in Jrooms)
                    {
                        rooms.Add((int)room[0], (string)room[1]);
                    }

                    foreach (KeyValuePair<int, string> roomInDict in rooms)
                    {
                        this.Dispatcher.Invoke((Action)(() =>
                        {
                            roomsList.Items.Add(new Label().Content = $"{roomInDict.Key}: {roomInDict.Value}");
                        }));
                    }

                }
                else if (response.ContainsKey("message"))
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {
                        roomsListErrorBox.Text = (string)response["message"];
                    }));
                }
                Thread.Sleep(3000);
            }
        }
        private void roomListBackButtonClick(object sender, RoutedEventArgs e)
        {
            refreshRoomsListThread.Abort();

        }
        private void mainMenuJoinRoomButtonClick(object sender, RoutedEventArgs e)
        {
            roomsListErrorBox.Text = "";

            refreshRoomsListThread = new Thread(refreshRoomList);
            refreshRoomsListThread.Start();

        }
    }
}

您可以设置一个标志以最终退出 while 循环,而不是尝试强制中止线程:

private bool _run = true;
public void refreshRoomList()
{
    while (_run)
    {
        ...
    }
}
private void roomListBackButtonClick(object sender, RoutedEventArgs e)
{
    _run = false;
}

您应该将 DispatcherTimerasync Tick 事件处理程序一起使用,该事件处理程序在 Task 中运行 long-运行 操作。

Tick 事件处理程序在 UI 线程中执行,因此您不需要使用 Dispatcher。

private readonly DispatcherTimer timer = new DispatcherTimer
{
    Interval = TimeSpan.FromSeconds(3)
};

public MainWindow()
{
    StartClient();
    InitializeComponent();

    timer.Tick += OnTimerTick;
}

private void mainMenuJoinRoomButtonClick(object sender, RoutedEventArgs e)
{
    timer.Start();
}

private void roomListBackButtonClick(object sender, RoutedEventArgs e)
{
    timer.Stop();
}

private async void OnTimerTick(object sender, EventArgs e)
{
    roomsListErrorBox.Text = "";

    Dictionary<string, object> response = await Task.Run(
        () =>
        {
            serializeAndSendMessage(GET_ROOMS_REQUEST, "");

            return receiveAndDeserializeMessage();
        });


    if (response.ContainsKey("status") && (string)response["status"] == "1")
    {
        roomsList.Items.Clear();
        // ...
    }
}

要解决此问题,您可以使用布尔值并让线程处于活动状态,这是一个示例:

        public bool KeepAlive { get; set; } = true;
    private void YourThread()
    {


        while (KeepAlive)
        {
            //Do your task here
        }
    }

当你想停止线程时设置 KeepAlive = false;