Red X GUI вылетает! Я почти разочаровался в решении этого! - PullRequest
6 голосов
/ 05 января 2010

Я сталкиваюсь со сложной ошибкой, связанной с инструментом Dundas Charting for Winforms, который используется в MS Visual Studio 2008 C #.

Следующая ошибка возникает при возникновении события GUI для объекта Chart во время его аннулирования. Когда происходит ошибка, диаграмма 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)

Сценарий таков:

  • У меня есть сетка, в которой есть список объектов, которые ссылаются на наносимый ряд.
  • График обновляется каждую 1 секунду, используя chart.Invoke (AddData)

Это событие, которое вызывает сбой:

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;

            }
        }
    }
}

Рисование выполняется следующим образом

Фоновая нить захватывает

Это событие поднимает

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);
    }
}

Интересной особенностью этой ошибки является то, что она встречается не на всех машинах. Я заметил, что это происходит на машинах с высокими техническими характеристиками, таких как наш 8-ядерный процессор DELL и новый четырехъядерный ноутбук, который мы получили здесь. Это вызвало подозрение на проблему с многопоточностью; тем не менее, с потоками все в порядке, поскольку доступ к объекту диаграммы осуществляется из того же основного потока.

Пожалуйста, помогите мне с этим

UPDATE присвоение с помощью установщика, которое происходит в функции dataGridView1_CellEndEdit MUChart.Series [boundData.SeriesName] .ChartArea = boundData.ChartArea.ToString (); вызывает диаграмму. внутренне в то время как вызываемая функция AddData, которая обновляет эту диаграмму, вызывает ее явно. Я прочитал в библиотеке MSDN, что «control.invalidate» не вызывает синхронную рисование, если после него не вызывается control.update. Я почти уверен, что конфликт происходит после аннулирования, даже если все происходит в одном потоке, поскольку перерисовка происходит асинхронно. Я понял, что происходит таким образом, но я не знаю, как этого избежать. control.update не приносит мне пользы.

ChangeTheChartConfigurations (); DrawTheChanges () ---- >>>> это работает асинхронно UpdateDataPoints () DrawTheChanges () ---- >>> это работает, пока первое изменение еще не произошло. Например, серия могла быть перемещена в область разностной диаграммы, и Dundas.Charting.WinControl.AxisScale.a (Double) (последняя функция в трассировке стека) вызывается в уже скрытой области диаграммы. это просто мысль

UPDATE

Я зарегистрировал идентификатор потока как из обработчика событий, так и из функции AddNewPoint, и он совпадал с основным потоком

Ответы [ 6 ]

2 голосов
/ 13 января 2010

Вместо того, чтобы сделать диаграмму недействительной после прорисовки каждой точки, нарисуйте все точки, а затем аннулируйте диаграмму один раз. Попробуйте переместить MUChart.Invalidate () из AddNewPoint () в после цикла for в AddData ().

2 голосов
/ 11 января 2010

Я думаю, что вы не должны звонить

MUChart.Series[boundData.SeriesName].ChartArea = boundData.ChartArea.ToString();

непосредственно. Вы должны заключить его в код InvokeRequired / Invoke. И то же самое для

MUChart.ChartAreas[boundData.ChartArea].Visible = true;
1 голос
/ 14 января 2010

Я подозреваю, что у вас есть объект, который был утилизирован. (Это своего рода странное исключение, которое вы получаете.) Вы указываете на то, что это происходит на компьютерах высокого уровня. Смысл, машина выполнила сборку мусора.

1) Что происходит, когда вы вызываете Обновить вместо Invalidate?

2) Удалите длинную цепочку ссылок на объекты и создайте переменные. Вы понимаете, что каждый {} создает локальную область (стек). Что может привести к изменению области объекта во время обновления диаграммы. Do Series s = MUChart.Series[boundData.SeriesName]; ChartArea a = s.ChartArea; и т. д.

3) Попробуйте заблокировать или синхронизировать объект в AddNewPoint или AddData. Также возможно то, что вы делаете, не является поточно-ориентированным для управления. Проверьте документацию.

4) Я бы не стал размещать try: catch в AddNewPoint. Лучше поместить его вне цикла for, но в вашем случае поместите его в цикл.

5) Вы действительно не должны использовать вызовы для обновления, обновления и аннулирования. Это признак того, что ваша реализация должна быть менее загруженной. (Например, при удалении try: catch, обращении к любым множественным событиям «Доступные данные», с помощью блокировки синхронизации удалите метод AddNewPoint.)

1 голос
/ 09 января 2010

Возможно, у вас операция с перекрестным потоком.

Попробуйте разместить свой MUChart.Invalidate после добавления всех точек и в главном потоке графического интерфейса.

Красный крест обычно рисуется самой .NET Framework при доступе к элементу управления пользовательского интерфейса из другого потока, чем поток пользовательского интерфейса.

Крест также отображается, когда ресурс недоступен или возникает исключение в элементе управления.

0 голосов
/ 07 декабря 2016

Я столкнулся с той же ошибкой и обнаружил, что я установил AxisIntervalMode в качестве VaiableCount, даже когда нет данных. Поэтому я динамически изменяю AxisIntervalMode в соответствии с тем, есть ли у серии данные. Надеюсь, что это может кому-то помочь.

0 голосов
/ 14 января 2010

Пожалуйста, обратите внимание на следующую ошибку:

Интервал не может быть нулевым. Параметр название: diff

Я думаю, что два значения для оси x диаграммы имеют одинаковое значение, поэтому возникает исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...