C#(blazor实现)中线程的开始、暂停、继续、停止与定时关闭代码实现
C# 中线程控制:使用 CancellationTokenSource
和 ManualResetEvent
在现代应用程序中,线程控制是一个重要的主题,尤其是在处理并发任务时。C# 提供了多种工具来管理线程的启动、停止和同步。在本文中,我们将深入探讨如何使用 CancellationTokenSource
类来控制线程的开始与停止,以及如何使用 ManualResetEvent
类来实现线程的阻塞与非阻塞。
代码实现
我们将通过一个 Blazor 组件示例来展示这些概念。以下是 TaskTest.razor
的完整代码实现:
TaskTest.razor
@page "/Task"
<div class="main">
<h1>线程控制</h1>
<p role="status" style="margin:20px 0;">提示信息: @_message</p>
<button @onclick="Start" style="margin-right:20px;">开始</button>
<button @onclick="Pause" style="margin-right:20px;">暂停</button>
<button @onclick="Continue" style="margin-right:20px;">继续</button>
<button @onclick="Stop" style="margin-right:20px;">停止</button>
<input type="number" @bind-value="@_milliseconds" />
<button @onclick="Timing" style="margin-right:20px;">定时取消</button>
</div>
@code {
private string _message = "";
private CancellationTokenSource? _tokenSource; // 用于终止线程
private ManualResetEvent? _manualReset; // 用于阻塞/恢复线程运行
private int _milliseconds = 1000;
private void Start() {
if (_tokenSource != null) {
Pause();
Thread.Sleep(200);
_message = "一次只能创建一个线程!请点击继续开启当前线程!";
StateHasChanged();
return;
}
_tokenSource = new();
_manualReset = new(true);
int i = 0;
Task.Run(() => {
while (!_tokenSource.Token.IsCancellationRequested) {
_manualReset.WaitOne(); // 根据是否收到信号判断是否阻塞当前线程
Thread.Sleep(200);
_message = $"线程{Environment.CurrentManagedThreadId}正在运行第{++i}次{Environment.NewLine}";
InvokeAsync(() => { StateHasChanged(); return Task.CompletedTask; });
}
CancelSuccess();
InvokeAsync(() => { StateHasChanged(); return Task.CompletedTask; });
}, _tokenSource.Token);
}
private void Pause() {
_manualReset?.Reset(); // 阻塞所有调用WaitOne()的线程
}
private void Continue() {
_manualReset?.Set(); // WaitOne()阻塞的等待线程将恢复并继续执行
}
private void Stop() {
_tokenSource?.Cancel(); // 关闭线程
StateHasChanged();
}
private void Timing() {
_tokenSource?.CancelAfter(_milliseconds); // 定时关闭线程
}
private void CancelSuccess() {
_tokenSource = null;
_manualReset = null;
_message = "线程取消成功!";
}
}
TaskTest.razor.css
.main {
padding: 20px;
background: gray;
}
button {
display: inline-block;
margin: 0;
padding: 0 20px;
height: 40px;
border: 1px solid #fff;
border-radius: 4px;
font-size: 14px;
color: #fff;
background: rgba(68, 68, 68, 0.5);
cursor: pointer;
}
input {
height: 40px;
border: none;
border-radius: 4px;
font-size: 12px;
color: #fff;
text-indent: 1em;
background: #444;
outline: none;
}
界面展示
在上述代码中,我们创建了一个简单的用户界面,允许用户控制线程的启动、暂停、继续和停止。以下是界面的示例截图:
代码解析
1. 使用 CancellationTokenSource
控制线程
CancellationTokenSource
是一个用于管理线程取消的类。通过创建一个 CancellationTokenSource
实例,我们可以在需要时请求取消线程的执行。在 Start
方法中,我们检查是否已有线程在运行,如果没有,则创建一个新的 CancellationTokenSource
和 ManualResetEvent
实例。
if (_tokenSource != null) {
Pause();
Thread.Sleep(200);
_message = "一次只能创建一个线程!请点击继续开启当前线程!";
StateHasChanged();
return;
}
_tokenSource = new();
2. 使用 ManualResetEvent
实现线程阻塞与恢复
ManualResetEvent
是一个线程同步类,允许我们控制线程的执行。通过调用 Reset
方法,我们可以阻塞线程,而调用 Set
方法则可以恢复线程的执行。
private void Pause() {
_manualReset?.Reset(); // 阻塞所有调用WaitOne()的线程
}
private void Continue() {
_manualReset?.Set(); // 恢复线程执行
}
3. 定时取消线程
在 Timing
方法中,我们使用 CancelAfter
方法来设置一个定时器,指定在一定时间后自动取消线程。这使得我们可以灵活地控制线程的生命周期。
private void Timing() {
_tokenSource?.CancelAfter(_milliseconds); // 定时关闭线程
}
应用场景
这种线程控制机制在许多应用场景中都非常有用,例如:
- 后台任务处理:在需要处理长时间运行的任务时,可以使用这些机制来控制任务的执行。
- 用户交互:在用户界面中,允许用户通过按钮来控制任务的执行状态,提升用户体验。
- 资源管理:在资源有限的情况下,能够及时停止不必要的线程,节省系统资源。
总结
本文介绍了如何在 C# 中使用 CancellationTokenSource
和 ManualResetEvent
来控制线程的启动、停止和阻塞。通过示例代码,我们展示了如何在 Blazor 应用中实现这些功能。掌握这些技术将有助于开发更高效和响应迅速的应用程序。希望这篇文章能为你在 C# 线程管理方面提供一些有用的见解和实践经验。
- 点赞
- 收藏
- 关注作者
评论(0)