C# 使用ManualResetEvent和CancellationTokenSource,后台线程,实现后台数据获取(方法为GetValueData)和界面中的chart刷新(方法为GetChartData)功能的启动、继续、暂停和停止功能 给出完整程序
时间: 2024-09-12 21:04:56 浏览: 29
在C#中,我们可以使用`System.Threading.Tasks.Task`、`ManualResetEvent`以及`CancellationTokenSource`来控制后台线程的工作流程,并结合`System.Windows.Forms.DataVisualization.Charting.Chart`更新图表。下面是一个简单的示例,展示了如何实现实验所需的启动、继续、暂停和停止功能:
```csharp
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading;
public partial class MainForm : Form
{
private CancellationTokenSource _cancellationTokenSource;
private ManualResetEventSlim _resetEvent = new ManualResetEventSlim(initialState: false);
private Chart chart;
public MainForm()
{
InitializeComponent();
chart = Controls.Add(new Chart());
chart.ChartAreas.Add("Main");
chart.Series.Add("ValueSeries", Color.Blue);
}
private async void startButton_Click(object sender, EventArgs e)
{
if (_cancellationTokenSource != null)
throw new InvalidOperationException("已启动,请先停止");
_cancellationTokenSource = new CancellationTokenSource();
Task.Run(() => GetValueData(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
StartRefresh();
}
private void pauseButton_Click(object sender, EventArgs e)
{
if (!_cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource.Cancel();
}
private void resumeButton_Click(object sender, EventArgs e)
{
if (_cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource.Reset();
}
private void stopButton_Click(object sender, EventArgs e)
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Dispose(); // 确保取消并释放资源
_cancellationTokenSource = null;
_resetEvent.Set(); // 设置手动重置事件以唤醒等待线程
}
}
private void GetChartData(int value)
{
// 更新图表数据
chart.Series["ValueSeries"].Points.AddXY(DateTime.Now, value);
chart.Invalidate();
Application.DoEvents(); // 刷新UI以立即显示新数据
}
private async void GetValueData(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
int data = await GetDataAsync(cancellationToken); // 模拟异步数据获取
GetChartData(data);
}
catch (OperationCanceledException)
{
break; // 如果操作被取消,则退出循环
}
}
_resetEvent.Wait(); // 等待手动重置事件,释放线程
}
private async Task<int> GetDataAsync(CancellationToken cancellationToken)
{
// 实现数据获取的异步函数,这里为了简单演示,可以设置一些延迟
await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
return Random.Range(0, 100);
}
private void StartRefresh()
{
_resetEvent.WaitOne(); // 等待手动重置事件,当停止按钮按下时,这里会立即返回
_resetEvent.Reset();
}
}
```
在这个例子中,我们创建了一个`CancellationTokenSource`来管理任务的开始、暂停和停止。`GetValueData`函数会在后台持续获取数据,直到收到`CancellationToken`。`StartRefresh`用于同步图表刷新的开始。
请注意这只是一个简化版本的示例,实际应用中你可能需要处理更复杂的错误情况和优化数据获取过程。同时,`Application.DoEvents()`并不是一个好的实践,因为它可能导致UI阻塞,除非必要,应尽量避免频繁使用。在真正的Windows Forms应用程序中,你可能会选择使用`SynchronizationContext`或者`Control.Invoke`来进行UI更新。