mus*_*bar 6 c# crash user-interface winforms
我正面临着与MS Visual Studio 2008 C#一起使用的Dundas Charting for Winforms工具的复杂错误.
当Chart对象在其无效时引发GUI事件时,会发生以下错误.当错误发生时,dundas图表显示一个很大的X标记....
************** Exception Text **************
System.ArgumentOutOfRangeException: Axis Object - The Interval can not be zero
Parameter name: diff
at Dundas.Charting.WinControl.AxisScale.a(Double )
at Dundas.Charting.WinControl.Axis.a(Double , Double , AxisScaleSegment , DateTimeIntervalType& )
at Dundas.Charting.WinControl.Axis.a(ChartGraphics , Boolean , AxisScaleSegment , Boolean )
at Dundas.Charting.WinControl.Axis.b(ChartGraphics , Boolean , Boolean )
at Dundas.Charting.WinControl.Axis.Resize(ChartGraphics chartGraph, ElementPosition chartAreaPosition, RectangleF plotArea, Single axesNumber, Boolean autoPlotPosition)
at Dundas.Charting.WinControl.ChartArea.a(ChartGraphics )
at Dundas.Charting.WinControl.ChartPicture.Resize(ChartGraphics chartGraph, Boolean calcAreaPositionOnly)
at Dundas.Charting.WinControl.ChartPicture.Paint(Graphics graph, Boolean paintTopLevelElementOnly, RenderingType renderingType, XmlTextWriter svgTextWriter, Stream flashStream, String documentTitle, Boolean resizable, Boolean preserveAspectRatio)
at Dundas.Charting.WinControl.ChartPicture.Paint(Graphics graph, Boolean paintTopLevelElementOnly)
at Dundas.Charting.WinControl.Chart.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Run Code Online (Sandbox Code Playgroud)
方案如下:
这是导致崩溃的事件:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
{
AppDataSeries boundData =
dataGridView1[e.ColumnIndex, e.RowIndex].OwningRow.DataBoundItem as AppDataSeries;
if (boundData.Tag != null)
// Tag is of Type Dundas.Charting.WinControl.Series
{
switch (e.ColumnIndex)
{
case 1:
MUChart.Series[boundData.SeriesName].ChartArea =
boundData.ChartArea.ToString();
// when you change the chart area of a series it
// crashes the chart control
// also when you enable or disable a series using
// series1.Enabled = true,
// it could crash the chart control
MUChart.ChartAreas[boundData.ChartArea].Visible = true;
break;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
绘图以下列方式完成
后台线程正在捕获
它正在提升这一事件
OnDataAvailable每秒
这是处理程序
void serviceWrapperInstance_DataAvailable(object sender, DataAvailableEventArgs e)
{
if (e.ViewId == currentViewId)
{
if (MUChart.InvokeRequired)
{
MUChart.Invoke((MethodInvoker)AddData);
}
else
{
AddData();
}
}
}
public void AddData()
{
if (MUChart.Series.Count > 0)
{
for (int i = 0; i < currentViewSeries.Count; i++)
{
AddNewPoint(currentViewSeries[i].XValue, MUChart.Series[i],
currentViewSeries[i].YValue * ((currentViewSeries[i].IsInverse) ? -1 : 1),
currentViewSeries[i].ChartColor);
dataSaver[MUChart.Series[i].Name].Add(new DataPoint(currentViewSeries[i].XValue,
(double)currentViewSeries[i].YValue));
}
}
}
public void AddNewPoint(double xValue, Series ptSeries, double yValue,
Color pointColor)
{
try
{
ptSeries.Points.AddXY(xValue, yValue);
if (draggedDroppedSeriesMapper.ContainsKey(ptSeries))
foreach (Series item in draggedDroppedSeriesMapper[ptSeries].DraggedDroppedSeriesVersions)
item.Points.AddXY(xValue, yValue);
MUChart.Invalidate();
// if I remove the previous line the plot doesn’t crash, but doesn’t update !!
}
catch (Exception ex)
{
Logger.Log(TraceLevel.Error, "AddNewPoint()", ex);
}
}
Run Code Online (Sandbox Code Playgroud)
关于这个bug的有趣之处在于它不会在所有机器上发生.我注意到它发生在高规格的机器上,比如我们的8核CPU DELL机器,以及我们在这里购买的新四核笔记本电脑.这引起了线程问题的嫌疑人; 但是,线程似乎没问题,因为图表对象是从同一主线程访问的.
请在这件事上给予我帮助
使用函数dataGridView1_CellEndEdit MUChart.Series [boundData.SeriesName]中发生的setter 更新赋值.ChartArea = boundData.ChartArea.ToString(); 在内部调用chart.invalidate,而更新该图表的调用函数"AddData"显式调用它.我在MSDN库中读到"control.invalidate"不强制同步绘制,除非在它之后调用control.update.我几乎可以肯定,即使一切都发生在同一个线程上,由于重绘正在异步进行,冲突也会在失效时发生.我理解这种情况正在发生,但我不知道如何避免它.control.update对我没有好处.
ChangeTheChartConfigurations(); DrawTheChanges()---- >>>>这是异步工作的UpdateDataPoints()DrawTheChanges()---- >>>这在第一次更改尚未发生时有效.例如,系列可能已被移动到差异图表区域,Dundas.Charting.WinControl.AxisScale.a(Double)(堆栈跟踪中的最后一个函数)正在已隐藏的图表区域上调用..这只是一个想法
UPDATE
我从事件处理程序和AddNewPoint函数中记录了线程ID,它与主线程相同
不要在绘制每个点后使图表失效,而是绘制所有点,然后使图表一次失效。尝试将 MUChart.Invalidate() 从 AddNewPoint() 移至 AddData() 中的 for 循环之后。