How to catch a TargetInvocationException from .Net BackgroundWorker in Matlab?

I am writing a small application in Matlab using GUIDE. This application requires the .Net library. The library is connected to a serial device. Using BackgroundWorker, the library examines the port for new data and raises an event IncomingDatawhenever a new packet is received. (I know this because I used the decompiler to view the guts of the library.)

The problem is that the SDK I usedRunWorkerCompleted did not apply the method correctly . It does not check if an exception occurred through the property e.Errorsbefore accessing the property e.Result. This throws a TargetInvocationException . This exception will be unhandled and will cause Matlab to crash with the next event in the Windows event log. An internal exception is not serialized in the event log, so I don’t know what actually causes the failure.

Application: MATLAB.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Reflection.TargetInvocationException
Stack:
   at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()
   at System.ComponentModel.RunWorkerCompletedEventArgs.get_Result()
   at TargetInvocationIssueMVCE.BlackBox._backgroundWorker_RunWorkerCompleted(System.Object, System.ComponentModel.RunWorkerCompletedEventArgs)
   at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(System.ComponentModel.RunWorkerCompletedEventArgs)
   at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(System.Object)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,  System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

I was able to reproduce the behavior of the library that I am using with the following C # class library. You can think of this example BlackBoxbelow as a library that I cannot change.

using System;
using System.ComponentModel;

namespace TargetInvocationIssueMVCE
{
    public class BlackBox
    {
        private BackgroundWorker _backgroundWorker;

        public event EventHandler<EventArgs> IncomingData;

        public void Connect()
        {
            _backgroundWorker = new BackgroundWorker()
            {
                WorkerSupportsCancellation = true
            };

            _backgroundWorker.DoWork += _backgroundWorker_DoWork;
            _backgroundWorker.RunWorkerCompleted += _backgroundWorker_RunWorkerCompleted;
            _backgroundWorker.RunWorkerAsync();
        }

        private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // BlackBox should check e.Errors first, but doesn't, so throws a TargetInvocationException that I can't seem to catch, so it crashes Matlab.
            Console.Write(e.Result == null ? "Failure" : "Success");
        }

        private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            throw new InvalidOperationException("I could be any exception.");

            // the real worker is supposed to raise IncomingData here.
        }
    }
}

I call this library in the Matlab GUI GUI like this.

% --- Executes just before Figure1 is made visible.
function Figure1_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to Figure1 (see VARARGIN)

% load the library

NET.addAssembly('C:\path\to\TargetInvocationIssueMVCE.dll');
blackbox = TargetInvocationIssueMVCE.BlackBox();
handles.blackbox = blackbox;

addlistener(blackbox, 'IncomingData', @OnIncomingData);

% Choose default command line output for Figure1
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% ... some other irrelevant callbacks

% --- button click callback starts .Net BackgroundWorker process
function btnConnect_Callback(hObject, eventdata, handles)
try
    handles.blackbox.Connect();
    set(hObject, 'String', 'Disconnect');

catch ex
    warning(ex.message);
    set(hObject, 'Value', 1);
end

% --- Callback to process incoming data packets
function OnIncomingData(source, arg)
    % It doesn't matter what I put here, the exception is raised before
    % I ever get a packet event and Matlab crashes.

    msgbox('Received Packet');

.Net, , catch static void Main(), .

try
{
    Application.Run(new Form1());
}
catch (TargetInvocationException exception)
{
    System.Windows.Forms.MessageBox.Show(exception.InnerException.ToString());
}

Matlab, Script , . , - . Matlab - , , Figure1, .

try
    Figure1
catch ex
    warning(ex.message)
end

, , . , XY. , do , , , .


.

, , . "" , , .

, , script. ? , ?

+4

All Articles