System.InvalidOperationException: Type 'System.Double' is not supported

Charts for WPF Forum

Posted 1 year ago by Nerd22 - Germany
Version: 22.1.4
Avatar

Hello everybody,

I've written an WPF application on Visual Studio 2019 at work, where this really weired error sometimes (1) appears.

(1) This unhandled exception may appear, where the earliest time was under a minute,
and the latest one was over 3 1/2 hours, however, sometimes this exception may also
not appear during on test runs.

In my application I've some XYChart objects to display different LineSeries data of type double. The axes are able
to do an auto refresh (2) with a new minimum and maximum boundary.

(2) A month ago I had opened a topic about that old issue, which already has been solved.

However, when I got this unhandled exception, Visual Studio tells me, that this appeared somewhere in
ActiproSoftware.Charts.Wpf.dll and I don't have the required .pdb file, which might be helpful.
The basic "reason" is just "System.InvalidOperationException: Type 'System.Double' is not supported."

Here is a snippet, where this "unhandled" exception could appear, maybe not:

Dispatcher.Invoke(() => {
	try {
		/*	removing previous LineSeries 	*/
		chartRight.Series.Clear();

		/*	receiving new LineSeries object	*/
		LineSeries currentSeries = CurrentLineSeries(new List<Coordinates>(liveData.DataCollection), ChartSelector.ChartRight);
		chartRight.Series.Add(currentSeries);

		/*	---	auto refresh for my axis	---	*/

		/*	Could this be the cause of the exception?
		 *
		 *	Since the base class XYAxisBase doesn't comes with properties to setting up
		 *	the minimal and maximal value for my axes, a conversion to XYDoubleAxis
		 *	allows me to do this.
		*/
		XYDoubleAxis xyDA = (XYDoubleAxis)chartRight.YAxes.First();
		xyDA.Minimum = Convert.ToDouble(currentLiveData.MinValue);
		xyDA.Maximum = Convert.ToDouble(currentLiveData.MaxValue);

		/*	here the tick ranges for my XYaxis are going to refresh		*/
		axisBoundaries[ChartSelector.ChartRight].MinimalValue = Convert.ToInt32(currentLiveData.MinValue);
		axisBoundaries[ChartSelector.ChartRight].MaximalValue = Convert.ToInt32(currentLiveData.MaxValue);

		SetStepRanges(ref xyDA, axisBoundaries[ChartSelector.ChartRight]);

		chartRight.Refresh();
	} catch (Exception e) {
		/*	unlike the exception shall be handled here, it won't	*/

		Console.Error.WriteLine("{0}{1}{2}, e.Message, Environment.NewLine, e.StackTrace");

		if (e is InvalidOperationException ioe) {
			/*	since the exception is marked as "unhandled", I never get a more clear information about 
				where, when and why this happens
			*/
			using(LogOutput lo = new LogOutput()) {
				lo.WriteToLog(String.Format("HRESULT: {0}, SOURCE: {1}{2}", ioe.HResult, ioe.Source, Environment.NewLine), LogState.DEBUG);
			}
		
			if (ioe.Data != null) {
				foreach(Object o in ioe.Data) {
					Console.Error.WriteLine(o);

					using(LogOutput lo = new LogOutput()) {
						lo.FullPathLogFile = AbsLogPath;
						lo.WriteToLog(o.ToString(), LogState.DEBUG);
					}
				}
			}
		}
	}
}, DispatcherPriority.Render);

CurrentLiveData() function:

private LineSeries CurrentLiveData(List<Coordinates> dataSource, ChartSelector chartSide) {
	LineSeries ls = new LineSeries() {
		XPath = "X",
		YPath = "Y",
		ItemsSource = dataSource
	};

	if (chartSide == ChartSelector.ChartLeft) {
		ls.LineKind = XYSeriesLineKind.Step;
	} else {
		ls.LineKind = XYSeriesLineKind.Spline;
	}

	return ls;
}

SetStepRanges() function:

private void SetStepRanges(ref XYDoubleAxis axis, AxisBoundary boundarySource, bool isXAxis = false) {
	double majorInterval;
	double minorInterval;

	try {
		/*	determining step ranges for charts	*/
		switch(boundarySource.RangeDetector) {
			case BoundaryRange.Steps10:
				majorInterval = Convert.ToDouble(1);
				minorInterval = Convert.ToDouble(0);
				break;
			case BoundaryRange.Steps20:
				/*	...	*/
				break;
				
			/*	...	*/
			
			case BoundaryRange.Steps25000:
				majorInterval = Convert.ToDouble(5000);
				minorInterval = Convert.ToDouble(2500);
				break;
			default:
				majorInterval = Convert.ToDouble(10000);
				minorInterval = Convert.ToDouble(5000);
				break;
		}
	} catch (Exception e) {
		Console.Error.WriteLine("{0}{1}{2}, e.Message, Environment.NewLine, e.StackTrace");
	}

	axis.TickMajorInterval = majorInterval;
	axis.TickMinorInterval = minorInterval;
}


The given stack trace by Visual Studio is also unclear for me:

Unhandled exception: System.InvalidOperationException: Type 'System.Double' is not supported.
   at ActiproSoftware.Windows.Controls.Charts.Primitives.DataTypeHelper.Average(Object average, Int32 count, Object newValue)
   at ActiproSoftware.Windows.Controls.Charts.XYDataPointCollectionView.<CreateDataPointsWithoutResolvedValues>d__45.MoveNext()
   at ActiproSoftware.Windows.Controls.Charts.XYDataPointCollectionView.P20(IEnumerable`1 )
   at ActiproSoftware.Windows.Controls.Charts.XYDataPointCollectionView.Initialize()
   at ActiproSoftware.Windows.Controls.Charts.Primitives.XYSeriesBase.PrepareSeries(IXYAxisPlotter primaryAxis, IXYAxisPlotter secondaryAxis, Size plotSize)
   at ActiproSoftware.Windows.Controls.Charts.Primitives.XYChartPlotter.XDQ(Size )
   at ActiproSoftware.Windows.Controls.Charts.Primitives.XYChartPlotter.Prepare(Size plotSize)
   at ActiproSoftware.Windows.Controls.Charts.Primitives.ChartPanel.MeasureOverride(Size availableSize)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at test.App.Main()


The application "[18184] test.exe" has been terminated with code 0 (0x0).

Can you figure out what's wrong here?

It that a possible bug in your API?

Comments (1)

Posted 1 year ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

I'm sorry you're running into trouble here.  Looking at the DataTypeHelper.Average method, it calculates a rolling average.  It gets passed the current "average" value (an Object), the count of data points so far, and the new value to build into the rolling average (an Object).  It then does comparisons of Types since you could be passing in doubles, decimals, DateTimes, etc.  If the "average" and "newValue" aren't of the same Type, then it throws that exception. 

In your case, it would say that exception if "average" is a Double, but newValue is NOT a Double.

Therefore my guess is that somehow you might be passing in data values where some are Doubles and some are not Doubles and that is what causes the problem.  It's hard to say without debugging it though, but that is what I would look for.  Make sure all your data point values being passed in are of type Double for this chart.  If so, you shouldn't run into this.  We aren't aware of any bugs in this area and the code has been the same for a while.  

If you are in the VS debugger when this happens, see which Type the "newValue" passed to the Average method is.  That might give you a clue as to what's going on.  Such as, could you be passing in an Int32 instead in some cases?

If that doesn't help narrow things down, please see if you can reproduce it consistently (I know you said it was sporadic) and then send us a new simple sample that shows it happening and we can debug what's going on.


Actipro Software Support

The latest build of this product (v24.1.2) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.