C# 中止线程:此平台不支持线程中止
C# Aborting a thread: Thread abort is not supported on this platform
问题
我在 c# (on windows 10 中创建了一个线程,它向服务器请求一些数据:
- 每次用户进入某个菜单时都应创建这样的线程(
mainMenuJoinRoomButtonClick()
)
- 每次用户退出该菜单时都应将其关闭(我们使用
roomListBackButtonClick()
退出)
这样做是为了让我们节省资源 和防止错误 如果线程没有关闭就会发生错误。 (请看下面的代码)
我尝试使用 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;
}
您应该将 DispatcherTimer
与 async
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;
问题
我在 c# (on windows 10 中创建了一个线程,它向服务器请求一些数据:
- 每次用户进入某个菜单时都应创建这样的线程(
mainMenuJoinRoomButtonClick()
) - 每次用户退出该菜单时都应将其关闭(我们使用
roomListBackButtonClick()
退出)
这样做是为了让我们节省资源 和防止错误 如果线程没有关闭就会发生错误。 (请看下面的代码)
我尝试使用 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;
}
您应该将 DispatcherTimer
与 async
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;