我希望“暂停”图表的系列更新以完成某些工作(例如,当我单击它时有一个按钮将暂停图表更新,然后单击“恢复”按钮时,它将更新系列中的所有暂停点。
我知道
chart1.Series.SuspendUpdates();
但它似乎不适用于我。我使用mschart示例-实时数据(线程安全)。
这是完整的代码
public partial class RealTimeSample : Form
{
public RealTimeSample()
{
InitializeComponent();
}
private Thread addDataRunner;
private Random rand = new Random();
public delegate void AddDataDelegate();
public AddDataDelegate addDataDel;
private void RealTimeSample_Load(object sender, System.EventArgs e)
{
// create the Adding Data Thread but do not start until start button clicked
ThreadStart addDataThreadStart = new ThreadStart(AddDataThreadLoop);
addDataRunner = new Thread(addDataThreadStart);
// create a delegate for adding data
addDataDel += new AddDataDelegate(AddData);
}
/// Main loop for the thread that adds data to the chart.
/// The main purpose of this function is to Invoke AddData
/// function every 1000ms (1 second).
private void AddDataThreadLoop()
{
while (true)
{
chart1.Invoke(addDataDel);
Thread.Sleep(1000);
}
}
public void AddData()
{
DateTime timeStamp = DateTime.Now;
foreach (Series ptSeries in chart1.Series)
{
AddNewPoint(timeStamp, ptSeries);
}
}
/// The AddNewPoint function is called for each series in the chart when
/// new points need to be added. The new point will be placed at specified
/// X axis (Date/Time) position with a Y value in a range +/- 1 from the previous
/// data point's Y value, and not smaller than zero.
public void AddNewPoint(DateTime timeStamp, System.Windows.Forms.DataVisualization.Charting.Series ptSeries)
{
double newVal = 0;
if (ptSeries.Points.Count > 0)
{
newVal = ptSeries.Points[ptSeries.Points.Count - 1].YValues[0] + ((rand.NextDouble() * 2) - 1);
}
if (newVal < 0)
newVal = 0;
// Add new data point to its series.
chart1.Series.SuspendUpdates();
ptSeries.Points.AddXY(timeStamp.ToOADate(), rand.Next(10, 20));
chart1.Series.SuspendUpdates();
// remove all points from the source series older than 1.5 minutes.
double removeBefore = timeStamp.AddSeconds((double)(90) * (-1)).ToOADate();
//remove oldest values to maintain a constant number of data points
while (ptSeries.Points[0].XValue < removeBefore)
{
ptSeries.Points.RemoveAt(0);
}
chart1.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddMinutes(2).ToOADate();
}
/// Clean up any resources being used.
protected override void Dispose(bool disposing)
{
if ((addDataRunner.ThreadState & ThreadState.Suspended) == ThreadState.Suspended)
{
addDataRunner.Resume();
}
addDataRunner.Abort();
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
private void startTrending_Click_1(object sender, EventArgs e)
{
// Disable all controls on the form
startTrending.Enabled = false;
// and only Enable the Stop button
stopTrending.Enabled = true;
// Predefine the viewing area of the chart
var minValue = DateTime.Now;
var maxValue = minValue.AddSeconds(120);
chart1.ChartAreas[0].AxisX.Minimum = minValue.ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = maxValue.ToOADate();
// Reset number of series in the chart.
chart1.Series.Clear();
// create a line chart series
Series newSeries = new Series("Series1");
newSeries.ChartType = SeriesChartType.Line;
newSeries.BorderWidth = 2;
newSeries.Color = Color.OrangeRed;
newSeries.XValueType = ChartValueType.DateTime;
chart1.Series.Add(newSeries);
// start worker threads.
if (addDataRunner.IsAlive == true)
{
addDataRunner.Resume();
}
else
{
addDataRunner.Start();
}
}
private void stopTrending_Click_1(object sender, EventArgs e)
{
if (addDataRunner.IsAlive == true)
{
addDataRunner.Suspend();
}
// Enable all controls on the form
startTrending.Enabled = true;
// and only Disable the Stop button
stopTrending.Enabled = false;
}
}
编辑:
我发现只要您为Axis设置了minmum或maximum属性,即使您使用
,图表也将保持显示状态chart1.Series.SuspendUpdates();
致电SuspendUpdates()
之后,我不得不删除这些行,现在我可以看到图表系列已暂停
chart1.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddMinutes(2).ToOADate();
答案 0 :(得分:2)
MsChart确实直接支持此操作,确实使用Series.SuspendUpdates()
是一个好方法,但是您需要正确地做到这一点。 (但是,请参见下面的更新以了解缺点)
MSDN这样说:
在 Invalidate 方法之后,对 Invalidate 方法的调用将无效。 SuspendUpdates方法被调用。
如果多次调用SuspendUpdates方法,则需要 多次调用ResumeUpdates方法。
这可以解释为什么它对您不起作用:保持通话平衡至关重要。您需要自己跟踪它们,因为没有可以查询的计数器。但是,如果您过分ResumeUpdates
调用,则不会发生任何不良情况,多余的调用将被忽略,下一个SuspendUpdates
将再次暂停。
这是示例屏幕截图,请观看悬浮计数器。.
请注意,通常添加点会自动触发Invalidate
。如果您正在做其他事情,例如绘制Paint
事件等,则可能需要调用Chart.Invalidate()
会阻止的SuspendUpdates
,直到被相同数量的{{1 }} ..
或者,您也可以使用以下一种简单的解决方法:
ResumeUpdates
,然后通过
DataPoints
用作普通,或.. series.Add(theNewPoint)
用于已暂停模式。设置为暂停模式时,只需在清除之前将所有点添加到someList<DataPoint>.Add(theNewPoint)
。不幸的是,没有series.Points
,因此您将不得不使用points.AddRange
循环。也许foreach
可以帮助提高性能。
chart.SuspendLayout
和xAxis.Maximum
。通过将它们设置为固定值,您可以在不显示它们的情况下在右边添加点。要显示整个点集,您可以将它们重置为xAxis.Minimum values
。这可能对您有用,但也可能会干扰您的财产。 更新:如OP所述,当他更改double.NaN
的{{1}}和/或Minimum
时,数据将更新。在许多其他情况下也会显示相同的效果:
Maximum
Axis
chart.AreasRecalculateAxesScale();
或Size
。Color
的{{1}} 所以我猜想,每当Width
被操纵并被迫自行更新时,都需要更新的数据。
因此,由于更健壮解决方案,这可能会使第一种解决方法更好。