Acumatica: неожиданное поведение PXLongOperation, которое приводит к сбою пользовательского интерфейса без исключения - PullRequest
3 голосов
/ 11 марта 2020

У меня тяжелая операция, которая работала правильно (но слишком долго):

_terminationHandler.InsertOrUpdateEmployeeTerminationDetails(TerminationFilters.Current, EmployeeTerminationItems, EmployeeTerminations.Current);

В Графике, который определен следующим образом:

public class MPEmployeeTerminationMaint : PXGraph<MPEmployeeTerminationMaint>

, который генерирует содержимое сетки данных в этих 2 вкладки (будет создано несколько записей): enter image description here Мне было рекомендовано использовать PXLongOperation:

      public async virtual void MPEmployeeTermination_TerminationDate_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
    {
        PXLongOperation.StartOperation(this, () =>
        {
            _terminationHandler.InsertOrUpdateEmployeeTerminationDetails(TerminationFilters.Current, EmployeeTerminationItems, EmployeeTerminations.Current);
        });
    }

Операция начинается: enter image description here Однако через некоторое время происходит сбой пользовательского интерфейса (или что-то произошло): enter image description here Но исключение не выдается. Так что нет никаких исключений или других намеков на то, что произошло. Если вы измените редактируемое свойство, вы получите исключение: enter image description here Страница Acumatica "trace" будет пустой.

Если я не отправлю this на PXLongOperation, это проблема решена:

  PXLongOperation.StartOperation(Guid.NewGuid(), () =>
        {
            _terminationHandler.InsertOrUpdateEmployeeTerminationDetails(TerminationFilters.Current, EmployeeTerminationItems, EmployeeTerminations.Current);
        });

однако у меня нет тогда указания пользователю, что происходит длинная операция (очевидно: нет никакой связи между длинной операцией и пользовательским интерфейсом без this больше).

Что определяется неправильно?

Я хочу улучшить взаимодействие с пользователем и позволить ему продолжать работать с пользовательским интерфейсом, когда происходит тяжелая операция. Если я смогу достичь этой цели по-другому - это тоже нормально. Например, вместо этого я могу использовать Guid.NewGuid (), но тогда мне нужно вручную обновить sh пользовательский интерфейс и, кроме того, данные не будут сохранены.

Буду очень признателен за любой совет.

Ответы [ 2 ]

1 голос
/ 12 марта 2020

Я нашел причину проблемы. Я не понимаю, почему это происходит, и это знание не решает мою проблему, однако, это больше не загадка: когда мы вызываем

 PXLongOperation.StartOperation(this, () =>
    {
        _terminationHandler.InsertOrUpdateEmployeeTerminationDetails(TerminationFilters.Current, EmployeeTerminationItems, EmployeeTerminations.Current);
    });

, это фактически создает экземпляр графа снова и все свойства которые были ранее настроены, снова становятся нулевыми. Все должно быть настроено снова. Этот метод возвращает пустой перечисляемый. Тем не менее, я до сих пор не понимаю, почему график пуст и почему не выдается исключение. Поэтому я считаю, что решение состоит в тщательной отладке кода и обеспечении того, чтобы все свойства, views и c имели ожидаемые значения. В моем случае EmployeeTerminations.Current - это null. он не выдает исключение, потому что у меня есть условие, которое возвращает

return Enumerable.Empty<MPEmployeeTerminationItem>().ToList()

, когда currentEmployeeTermination равно null, но когда переопределение вашего представления является пустой коллекцией, ваш Current равен null. и в результате все «привязки» в вашем пользовательском интерфейсе потерпят неудачу. Надеюсь, это кому-нибудь поможет.

1 голос
/ 11 марта 2020

Случайно ли, в своей длительной работе, вы меняете ключевые поля вашего Текущего объекта? Под ключевыми полями я подразумеваю поля, помеченные как IsKey. Я сталкивался с вашим похожим поведением ранее, когда пытался изменить значения IsKey. Также не назначайте Current вашего основного Data View совершенно другому объекту, потому что это также может привести к тем же проблемам.

Еще одна вещь, вы можете изменить способ ссылки на график из вашего длинного операция. Вы не должны ссылаться на this непосредственно внутри метода вашей длинной операции, потому что это не позволит Acumatica выполнить код асинхронно. В идеале вы должны создать метод stati c. Недавно я говорил об этом с Acumatica, и они предлагают следующий подход.

   ...
    var graphCopy = this;
    PXLongOperation.StartOperation(this, delegate { 
        //Encapsulating the logic in static method and calling it this
        doMyBusinessLogic(graphCopy); 
    });

}

static void doMyBusinessLogic(MyGraph graph){ 
    //Here VS will throw an exception if references of this graph are used
}       

Если вы хотите обновить пользовательский интерфейс после длительной операции, рассмотрите возможность использования PXCustomInfo.

Для устранения проблемы было бы начать комментировать код из вашей длинной операции, а затем повторно протестировать. Это поможет вам определить, какой код вызывает проблему.

Наконец, еще одно предложение - попытаться вызвать Save.PressButton (адаптер) перед продолжительной работой. Это особенно необходимо, если вы начинаете длительную операцию с новой записью перед сохранением.

 [PXUIField(DisplayName = "Start", MapViewRights = PXCacheRights.Update,
  MapEnableRights = PXCacheRights.Update)]
 [PXProcessButton]
 protected virtual IEnumerable Start(PXAdapter adapter)
 {
     Save.PressButton(adapter); 
     //...
  }
...