Completing the SketchEditor with a double click sometimes causes the application to crash

2078
7
08-15-2018 07:04 AM
JonasHashagen
New Contributor II

I'm using the SketchEditor for editing an existing geometry and completing the modification with a double click.

[...]
this.view.MouseDoubleClick += this.ViewOnMouseDoubleClickWhileSketching;‍
geometry = await this.view.SketchEditor.StartAsync(this.SketchMode, configuration).ConfigureAwait(true);
[...]

private async void ViewOnMouseDoubleClickWhileSketching(object sender, MouseButtonEventArgs e)
{
    try
    {          
        // this.IsValid evaluates if the geometry is valid on all changes of the editor.
     if (this.IsValid && this.view.SketchEditor.CompleteCommand.CanExecute(null))
     {
         this.view.SketchEditor.CompleteCommand.Execute(null);
     }
    }
    catch (Exception exception)
    {
        [...]
    }
}

Sometimes the double click causes the following exception being thrown. This exception is causing the whole application to crash:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at Esri.ArcGISRuntime.UI.SketchEditor.UpdateNewGeometry(MapPoint point, Boolean useFeedbackGraphic)
   at Esri.ArcGISRuntime.UI.SketchEditor.AddVertexToPartCollection(MapPoint mapPoint, VertexPosition vertexPosition)
   at Esri.ArcGISRuntime.UI.SketchEditor.AddPoint(MapPoint mapPoint)
   at Esri.ArcGISRuntime.UI.SketchEditor.<MapView_GeoViewTapped>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
[...]
0 Kudos
7 Replies
JenniferNery
Esri Regular Contributor

I'm not able to reproduce. SketchEditor appear to have been started by SketchCreationMode, it doesn't look like it had input geometry. I may be missing something in my repro. Can you share SketchEditConfiguration parameters? I tried to simplify it down to this. I also tried starting editor from button click but I haven't seen it crash on stop or start.

MyMapView.Map = new Map(SpatialReferences.Wgs84);
MyMapView.MouseDoubleClick += (a, b) =>
{
    if ((MyMapView.SketchEditor.Geometry as Polygon)?.Parts?.FirstOrDefault()?.PointCount >= 4
        && MyMapView.SketchEditor.CompleteCommand.CanExecute(null))
        MyMapView.SketchEditor.CompleteCommand.Execute(null);
};
MyMapView.SpatialReferenceChanged += async (s, e) =>
{
      var config = new SketchEditConfiguration();
      var geom = await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Polygon, config).ConfigureAwait(true);
      MessageBox.Show(geom.ToJson());
};‍‍‍‍‍‍‍‍‍‍‍‍‍

Could this be specific to Windows 7? I seem to recall now that we had issues with detecting double click on Windows 7. One of the related issues in the past had this workaround:

private static int DoubleTapInMs = 550;
private static int TapTolerance = 100;
private int _lastTapTimestamp = int.MinValue;
private Point _lastTapPosition;

private void TheMap_PreviewStylusSystemGesture(object sender, StylusSystemGestureEventArgs e)
{
    if (e.SystemGesture == SystemGesture.Tap)
    {
        var position = e.GetPosition(this);
        var currentTimeStamp = e.Timestamp;
        var elapsedTimeInMs = currentTimeStamp - _lastTapTimestamp;
        double distance = Math.Pow(position.X - _lastTapPosition.X, 2) + Math.Pow(position.Y - _lastTapPosition.Y, 2);
        _lastTapTimestamp = currentTimeStamp;
        _lastTapPosition = position;
        if (elapsedTimeInMs < DoubleTapInMs && distance < TapTolerance)
        {
            e.Handled = true;
            if (TheMap.Editor.Complete.CanExecute(null))
                TheMap.Editor.Complete.Execute(null);
        }
    }
}
0 Kudos
JonasHashagen
New Contributor II

You're code is basically what causes the exception on my machine (Windows 7). The only thing I do aditionally is that I restart the SketchEditor after the execution of the complete command (with a delay to make sure everything is done). This helps me to reproduce the bug.

Here is the code I used. The whole solution is attached.

this.MyMapView.SpatialReferenceChanged += this.MyMapViewOnSpatialReferenceChanged;
this.MyMapView.GeoViewDoubleTapped += this.MyMapViewOnGeoViewDoubleTapped;
[...]

private async void MyMapViewOnGeoViewDoubleTapped(object sender, GeoViewInputEventArgs e)
{
    try
    {
        if ((this.MyMapView.SketchEditor.Geometry as Polyline)?.Parts?.FirstOrDefault()?.PointCount >= 2)
        {
            if (this.MyMapView.SketchEditor.CompleteCommand.CanExecute(null))
            {
                this.MyMapView.SketchEditor.CompleteCommand.Execute(null);

                // If the bug did not happen the SketchEditor gets restarted for easier reproduction.
                // However the bug does happen with or without the following code, but the application would have to be restarted multiple times eventually.
                await Task.Delay(500).ConfigureAwait(true);
                await this.MyMapView.SketchEditor.StartAsync(SketchCreationMode.Polyline).ConfigureAwait(true);
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, ex.GetType().Name);
    }
}

private async void MyMapViewOnSpatialReferenceChanged(object sender, EventArgs e)
{
    try
    {
        // Initial start of the SketchEditor, it gets restarted after the completion.
        await this.MyMapView.SketchEditor.StartAsync(SketchCreationMode.Polyline).ConfigureAwait(true);
    }
    catch (TaskCanceledException)
    {
        // Happens when canceling SketchEditor.
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, ex.GetType().Name);
    }
}

Could this be specific to Windows 7? I seem to recall now that we had issues with detecting double click on Windows 7.

I don't think that's the issue I have. The double click is getting detected correctly and the sketch editors complete command gets executed.

0 Kudos
JenniferNery
Esri Regular Contributor

Thank you for providing us repro code. I'm still unable to reproduce on my Windows 10 machine but I was able to repro on Windows 7 machine. The issue we had logged previously for Windows 7 was also triple-tap/click and the customer's use case was identical to yours they'd restart editor after it has completed.

Instead of subscribing to MouseDoubleClick or GeoViewDoubleTapped right away, can you do this only prior to starting editor and unhooking when done? You can then use this task below for button clicked, SpatialReferenceChanged, or GeoViewDoubleTapped handler. I've seen this to prevent crash on Windows 7.

private async Task RestartDrawAsync()
{
    try
    {
        this.MyMapView.GeoViewDoubleTapped += this.MyMapViewOnGeoViewDoubleTapped;
        // Initial start of the SketchEditor, it gets restarted after the completion.
        await this.MyMapView.SketchEditor.StartAsync(SketchCreationMode.Polyline).ConfigureAwait(true);
    }
    catch (TaskCanceledException)
    {
        // Happens when canceling SketchEditor.
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, ex.GetType().Name);
    }
    finally
    {
        this.MyMapView.GeoViewDoubleTapped -= this.MyMapViewOnGeoViewDoubleTapped;
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Alternatively, you can mark event handled if SketchEditor is enabled/active

this.MyMapView.GeoViewTapped += (s, e) => { e.Handled = MyMapView.SketchEditor.IsEnabled && MyMapView.SketchEditor.CancelCommand.CanExecute(null); };
0 Kudos
JonasHashagen
New Contributor II

The issue we had logged previously for Windows 7 was also triple-tap/click and the customer's use case was identical to yours they'd restart editor after it has completed.

Oh! In my case I'm just doing a double click. Sorry if I wasn't clear enough with that. So my repro steps using the repro solution basically is:

  1. Click once on the map view.
    This places one point on the map.
  2. Double click on the map view.
    This places another point to the map and completes the sketch editor. The exception happens here.
  3. Repeat from step 1 if not crashed.

Through debugging I notices that this leads to raising one GeoViewTapped event, another GeoViewTapped event and a GeoViewDoubleTapped event in that order:

  1. Raise GeoViewTapped event.
    [SketchEditor] Adds new point.
  2. Raise GeoViewTapped event.
    [SketchEditor] Adds new point.
  3. Raise GeoViewDoubleTapped event.
    [MyCode] Completes the SketchEditor.

My hypothesis is that the exception happens when the CompleteCommand gets executed before the SketchEditor has finished adding the new point.

Instead of subscribing to MouseDoubleClick or GeoViewDoubleTapped right away, can you do this only prior to starting editor and unhooking when done? You can then use this task below for button clicked, SpatialReferenceChanged, or GeoViewDoubleTapped handler. I've seen this to prevent crash on Windows 7.

I do the restart of the sketch editor to my code only for easier reproduction. In my real project I'm not restarting the sketch editor afterwards. The error can happen on the first CompleteCommand.Execute call inside the OnGeoViewDoubleTapped event. Nevertheless I tried your solution and added it into my reproduction project which sadly does not prevent the crash.

0 Kudos
JenniferNery
Esri Regular Contributor

I have logged a new issue for us. I'm able to consistently reproduce on Windows 7 although sometimes it takes a while to reproduce but haven't yet seen it happen on Windows 10. That's why I have a strong suspicion it has to do with the events. Perhaps a single click registers as double click.

Regardless, API should still not crash.

I have no math behind this but for my testing, adding an insignificant delay (await Task.Delay(25)) before evaluating PointCount allows point to be added before sketch is completed which seems to avoid the crash. 

0 Kudos
BradyHoukom1
New Contributor

I also have this exact problem... However I have Windows 10. I am using the MouseMove event to track the line of my polygon as suggested here Dynamic line when drawing from one vertex to another 

 

 

The issue happens when I am finished drawing my polygon (attached to GeoViewDoubleTapped) and the user double or triple clicks the map

0 Kudos
BradyHoukom1
New Contributor

I also have this exact problem... However I have Windows 10. I am using the MouseMove event to track the line of my polygon as suggested here Dynamic line when drawing from one vertex to another 

The issue happens when I am finished drawing my polygon (attached to GeoViewDoubleTapped) and the user double or triple clicks the map

0 Kudos