I'm developing a class library which uses a Form
to catch specific WndProc
messages and process them afterwards. Processing includes file operations. The library then publishes the processed values as public properties or events.
Question: What do I do when then processing throws a exception?
If I'll let it bubble up to the caller, where does it need to be catched? Since it's not a function/method which needs to be called.
Library Class:
public event EventHandler<CmmStateChangedEventArgs> CmmStateChanged;
public event EventHandler<MeasurementInfoEventArgs> MeasurementInfoChanged;
public event EventHandler<MeasurementPlanInfoEventArgs> MeasurementPlanInfoChanged;
public MeasurementPlanInfo MeasurementPlanInfo { get; private set; }
public MeasurementInfo MeasurementInfo { get; private set; }
public Status CMMStatus { get; private set; }
// event handler for internal form WndProc event
// _messageForm is a empty invisible form which catches specific WndProc messages and invokes a event if necessary
private async void _messageForm_CMMStateChanged(object sender, CmmStateChangedEventArgs e)
{
// this could throw
var command = await _stateManager.GetCommandFileAsync(Configuration.CMMObserverFolderPath);
var observer = await _stateManager.GetObserverFileAsync(Configuration.CMMObserverFolderPath);
var measInfo = new MeasurementInfo();
switch (e.Status)
{
case Status.Running:
if (command.state == "set_cnc_start")
{
// this could throw if observer is null
measInfo = new MeasurementInfo()
{
MeasurementPlanId = observer.planid,
ControllerType = observer.controllertyp,
DeviceGroup = observer.devicegroup,
FirmwareRevision = observer.firmWareRevision,
OperatorId = observer.operid,
PartNumber = observer.partnbinc,
MeasurementPlanFileName = command.planPath,
};
MeasurementInfo = measInfo;
MeasurementInfoChanged?.Invoke(this, new MeasurementInfoEventArgs() { MeasurementInfo = measInfo });
}
break;
case Status.Finished:
measInfo = new MeasurementInfo()
{
MeasurementPlanId = observer.planid,
ControllerType = observer.controllertyp,
DeviceGroup = observer.devicegroup,
FirmwareRevision = observer.firmWareRevision,
OperatorId = observer.operid,
PartNumber = observer.partnbinc,
ChrFilePath = command.chrPath,
HdrFilePath = command.hdrPath,
FetFilePath = command.fetPath
};
MeasurementInfo = measInfo;
MeasurementInfoChanged?.Invoke(this, new MeasurementInfoEventArgs() { MeasurementInfo = measInfo });
break;
case Status.Paused:
case Status.Stopped:
case Status.Exception:
default:
break;
}
CMMStatus = e.Status;
CmmStateChanged?.Invoke(this, new CmmStateChangedEventArgs() { Status = e.Status });
}
Calling Class:
public MainForm()
{
InitializeComponent();
apiConfiguration = new ApiConfiguration();
// where catch possible exception ?
api = new Calypso()
.Configure(apiConfiguration)
.Initialize();
api.CmmStateChanged = Api_CmmStateChanged;
api.MeasurementInfoChanged = Api_MeasurementInfoChanged;
api.MeasurementPlanInfoChanged = Api_MeasurementPlanInfoChanged;
}
CodePudding user response:
It depends. Which scope can interpret the exception and take action (API or caller)? What is being thrown? Does the exception, when thrown, mean that the caller's state is now out-of-sync and things are about to get bad? Could the API try to fix such a problem? Will the next working change event give the caller a full recovery? Is the caller potentially interested in these "periodic glitches(?)" - perhaps add a message missed event.
If the the exception is a critical failure, and the question is where to handle this in the caller: I recommend catching the exception and adding a failure event, then the caller can respond the best it can. Alternatively, the initialization could accept a callback action to call.