Подтвердить что ты не робот

С# не работает в сборке релизов

Попытка отладить проблему в приложении С#, я наткнулся на эту проблему, которая является причиной сбоя в работе приложения.

В основном у меня есть этот код:

double scale = 1;
double startScale = 1;
...
scale = (e.Scale - 1) * startScale;
if(scale <= 1)
    scale = 1;
...

Случается, что даже если scale больше 1, исключение входит внутрь, если scale заканчивается всегда 1.

Это происходит только в версии сборки.

Кто-нибудь имеет представление о том, что происходит?

ИЗМЕНИТЬ

Это почти (не хватает только ctor, который ничего не делает, настраиваемого элемента управления для Xamarin Forms, взятого из их примера, чтобы реализовать жест щепотки (здесь).

public class PinchView : ContentView
{
    private double StartScale = 1;
    private double CurrentScale = 1;
    private double XOffset = 0;
    private double YOffset = 0;

    ...

    private void PinchGesture_PinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        if (e.Status == GestureStatus.Started)
        {
            // Store the current scale factor applied to the wrapped user interface element,
            // and zero the components for the center point of the translate transform.
            StartScale = Content.Scale;
            Content.AnchorX = 0;
            Content.AnchorY = 0;
        }

        if (e.Status == GestureStatus.Running)
        {
            // Calculate the scale factor to be applied.
            CurrentScale += (e.Scale - 1) * StartScale;
            if(CurrentScale <= 1)
            {
                CurrentScale = 1;
            }

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
            // so get the X pixel coordinate.
            double renderedX = Content.X + XOffset;
            double deltaX = renderedX / Width;
            double deltaWidth = Width / (Content.Width * StartScale);
            double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
            // so get the Y pixel coordinate.
            double renderedY = Content.Y + YOffset;
            double deltaY = renderedY / Height;
            double deltaHeight = Height / (Content.Height * StartScale);
            double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;

            // Calculate the transformed element pixel coordinates.
            double targetX = XOffset - (originX * Content.Width) * (CurrentScale - StartScale);
            double targetY = YOffset - (originY * Content.Height) * (CurrentScale - StartScale);

            // Apply translation based on the change in origin.
            Content.TranslationX = targetX.Clamp(-Content.Width * (CurrentScale - 1), 0);
            Content.TranslationY = targetY.Clamp(-Content.Height * (CurrentScale - 1), 0);

            // Apply scale factor.
            Content.Scale = CurrentScale;
        }

        if (e.Status == GestureStatus.Completed)
        {
            // Store the translation delta of the wrapped user interface element.
            XOffset = Content.TranslationX;
            YOffset = Content.TranslationY;
        }
    }
}

Это шаги моего сеанса отладки (e.Scale был оптимизирован и не отображается, но вы можете увидеть изменение CurrentScale):

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

4b9b3361

Ответ 1

CurrentScale и StartScale являются полями экземпляра, а не полями методов, поэтому на них может воздействовать другой поток. Чтобы обнаружить какое-либо состояние гонки, вы можете поместить замок вокруг этого блока и снова отладить:

lock (StartScale) {
    // Calculate the scale factor to be applied.
    CurrentScale += (e.Scale - 1) * StartScale;
    if(CurrentScale <= 1)
    {
        CurrentScale = 1;
    }
}

Если это работает, вы должны иметь лучшие результаты с локальными переменными для уменьшения внешних помех (и, следовательно, удалить блокировку):

lock (StartScale) {
    // Calculate the scale factor to be applied.
    var localCurrentScale = CurrentScale + (e.Scale - 1) * StartScale;
    if(localCurrentScale <= 1)
    {
        CurrentScale = 1;
    } else CurrentScale = localCurrentScale;
}

Вы можете использовать инструменты, такие как Redgate Reflector или Telerik JustDecompile (бесплатно) для анализа вашей сборной сборки (она довольно читаема) и посмотреть, что было оптимизировано во время компиляции.

N.B.: StartScale - плохой замок, но подходит для этой отладки.