Асинхронный текст "Загрузка ..." в WPF - PullRequest
0 голосов
/ 04 мая 2019

Я пытаюсь заставить TextBlock отображаться на экране со словами «Загрузка ...» с количеством точек, меняющихся каждые полсекунды, чтобы указать, что файл в настоящее время анализируется.К сожалению, он не анимируется так, как я хочу, когда файл анализируется.Вот что у меня сейчас:

private void MainWindow_MIDIBrowseClick(object sender, RoutedEventArgs e)
{
    MIDIBrowseClick?.Invoke(this, e);

    OpenFileDialog browseDialog = new OpenFileDialog
    {
        Filter = "MIDI files (*.mid)|*.mid|All files (*.*)|*.*"
    };

    if (browseDialog.ShowDialog() == true)
    {
        try
        {
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { ShowLoadingText(tokenSource.Token); }));

            MIDIParser midiParse = new MIDIParser(File.ReadAllBytes(browseDialog.FileName));

            midiParse.fileName = browseDialog.SafeFileName;

            midiParse.ParseFile();
            NoteParser noteParse = new NoteParser(midiParse);
            noteParse.ParseEvents();

            tokenSource.Cancel();
            DataContext = new PianoRollView(midiParse, noteParse);
        }
        catch (InvalidOperationException)
        {
            MessageBox.Show("Error parsing MIDI file!", "Error");
        }
    }
}

Это вызывает метод ниже, который анимирует текст "Загрузка ...":

private async void ShowLoadingText(CancellationToken token)
{
    txtLoading.Visibility = Visibility.Visible;

    try
    {
        while (!token.IsCancellationRequested)
        {
            txtLoading.Text = "Loading";
            await Task.Delay(500, token);
            txtLoading.Text = "Loading.";
            await Task.Delay(500, token);
            txtLoading.Text = "Loading..";
            await Task.Delay(500, token);
            txtLoading.Text = "Loading...";
            await Task.Delay(500, token);
        }
    }
    catch (TaskCanceledException)
    {
        txtLoading.Visibility = Visibility.Hidden;
    }
}

Не уверен, что я делаю неправильно.Любая помощь будет оценена!

1 Ответ

1 голос
/ 04 мая 2019

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

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { ShowLoadingText(tokenSource.Token); }));

            await Task.Run(() => Thread.Sleep(5000)); // your parsing operation

            tokenSource.Cancel();
        }

        private async void ShowLoadingText(CancellationToken token)
        {
            txtLoading.Visibility = Visibility.Visible;

            try
            {
                while (!token.IsCancellationRequested)
                {
                    txtLoading.Text = "Loading";
                    await Task.Delay(500, token);
                    txtLoading.Text = "Loading.";
                    await Task.Delay(500, token);
                    txtLoading.Text = "Loading..";
                    await Task.Delay(500, token);
                    txtLoading.Text = "Loading...";
                    await Task.Delay(500, token);
                }
            }
            catch (TaskCanceledException)
            {
                txtLoading.Visibility = Visibility.Hidden;
            }
        }
    }
}

В приведенном выше примере вы увидите анимацию загрузки продолжительностью 5 секунд. Это достигается асинхронным вызовом Thread.Sleep(5000). В вашем случае вы должны написать метод, который будет выполнять операцию разбора:

    private void Parse()       
    {
        MIDIParser midiParse = new MIDIParser(File.ReadAllBytes(browseDialog.FileName));

        midiParse.fileName = browseDialog.SafeFileName;

        midiParse.ParseFile();
        NoteParser noteParse = new NoteParser(midiParse);
        noteParse.ParseEvents();
    }

И заменить Thread.Sleep(5000) его вызовом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...