Производный асинхронный делегат вызывается дважды

#c# #asynchronous #windows-runtime #async-await

#c# #асинхронный #windows-среда выполнения #асинхронный-ожидание

Вопрос:

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

Код выглядит следующим образом:

 public partial class ControlBase : UserControl {
public ControlBase() {
        this.InitializeComponent();
        //Buttons
        PickFileButton.Click  = pickFile;
}

protected virtual async void pickFile(object sender, RoutedEventArgs e) {

        var picker = new FileOpenPicker();
        picker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
        picker.FileTypeFilter.Add(".wmv");
        picker.FileTypeFilter.Add(".mp4");

        var file = await picker.PickSingleFileAsync();

        if (file == null) return;
        IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);

        inputFile = file;
        InputVideoElement.SetSource(stream, file.ContentType);

    }
}

public sealed partial class DerivedControl : ControlBase {

        public DerivedControl() {
            this.InitializeComponent();

            PickFileButton.Click  = pickFile;
        }
//This handler called twice
protected async override void pickFile(object sender, RoutedEventArgs e) {
        base.pickFile(sender, e);
        //some other actions
}
  

Когда я пытаюсь его отладить, я вижу следующее:
Когда я нажимаю кнопку на производном элементе управления, он вызывает override void pickFile() , который вызывает базовую реализацию. В базовом методе pickFile() выполнение богато var file = await picker.PickSingleFileAsync(); , а затем производный обработчик pickFile() вызывается во второй раз, и действия повторяются до var file = await picker.PickSingleFileAsync(); того же момента, после чего я получаю System.UnauthorizedAccessException .

То же самое действие с базовой кнопкой управления работает нормально. В чем может быть проблема? Заранее спасибо

Ответ №1:

Вы добавляете Click обработчик событий дважды: один раз в DerivedControl конструкторе и один раз в ControlBase конструкторе.

Если вам нужен только один обработчик (как я и ожидал), просто удалите подписку в DerivedControl конструкторе. Ваш переопределенный метод все равно будет вызван, потому что подписка в ControlBase конструкторе — это просто делегат, который будет вызывать метод виртуально.

Комментарии:

1. дааа, я только что увидел это, когда просматривал код здесь! Свежий взгляд очень полезен. Спасибо