Блокирующий поток пользовательского интерфейса не отображает компоненты пользовательского интерфейса другого окна. - PullRequest
0 голосов
/ 07 января 2019

В моем приложении есть сценарий, в котором мне нужно заблокировать поток пользовательского интерфейса при выполнении действия. Несмотря на то, что он заблокирован, у меня есть другое окно, в котором должно отображаться сообщение «выполнение действия, пожалуйста, подождите», когда пользовательский интерфейс заблокирован. Проблема в том, что окно появляется, но оно никогда не отображает сообщение. Пожалуйста помоги. Даже DoEvents () не помогают. Это просто так легко отображает сообщение

Примечание:

  1. Я не хочу, чтобы метод был асинхронным, потому что я хочу заблокировать пользовательский интерфейс при его запуске.
  2. Я не хочу говорить ShowDialog (), потому что он там просто блокируется.
 private void ViewModel_PerformPrimeAction(InstrumentAction Action)
    {
                bool abort = false;

                CommandRunningWindow cmdDialog = null;
                if (Action == InstrumentAction.Prime)
                {
                    if (Xceed.Wpf.Toolkit.MessageBox.Show((string)TryFindResource("ConfirmPrimeInstrument"),
                        ApplicationSettingsViewModel.Instance.ProductName, MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
                        return;

                    this.IsEnabled = false;
//This below line never shows the message.
                    cmdDialog = ShowCommandWindow(ViewModelsHelper.GetResourceString("PerformingPrime")); 

                   System.Windows.Forms.Application.DoEvents(); 
                }
                UIUtils.OverrideCursor = System.Windows.Input.Cursors.Wait;

                try
                {
                    // This operation takes 10 seconds
                    QXInstrumentViewModel.Instance.Prime(() => { if (abort) throw new RunAbortedException(null); });

                }
                catch (RunAbortedException)
                {
                    errorMessage = (string)TryFindResource("CompletePrimeInstrumentAborted");
                    cmdDialog?.Close();
                }
                catch (Exception ex)
                {
                    var message = QXInstrumentViewModel.ToErrorCode(ex);
                    TokenSource = new System.Threading.CancellationToken(true);
                    if (message != null)
                    {
                        errorMessage = string.Format((string)TryFindResource("CompletePrimeInstrumentWithError"), Convert.ToInt32(message), errorMessage);
                    }
                    else
                    {
                        errorMessage = (string)TryFindResource("CompletePrimeInstrumentWithUnknownError");
                    }
                    cmdDialog?.Close();
                }
                UIUtils.OverrideCursor = null;
                this.IsEnabled = true; 
    }

     public CommandRunningWindow ShowCommandWindow(string message)
            {
                CommandRunningWindow cmdDialog = new CommandRunningWindow();
                cmdDialog.Message = message;
                cmdDialog.Owner = WPFUtils.GetActiveWindow();
                cmdDialog.Show();
                return cmdDialog;
            }

CommandRunningWindow имеет свойство зависимости типа string (message), которое связано с текстовым блоком.

1 Ответ

0 голосов
/ 08 января 2019

Вы не можете одновременно блокировать и показывать сообщение в одной и той же ветке.

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

private void ViewModel_PerformPrimeAction(InstrumentAction Action)
{
    bool abort = false;

    CommandRunningWindow cmdDialog = null;
    if (Action == InstrumentAction.Prime)
    {
        if (Xceed.Wpf.Toolkit.MessageBox.Show((string)TryFindResource("ConfirmPrimeInstrument"),
            ApplicationSettingsViewModel.Instance.ProductName, MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
            return;

        this.IsEnabled = false;
        //This below line never shows the message.
        cmdDialog = ShowCommandWindow(ViewModelsHelper.GetResourceString("PerformingPrime"));
    }
    UIUtils.OverrideCursor = System.Windows.Input.Cursors.Wait;

    Task.Factory.StartNew(() =>
    {
        // This operation takes 10 seconds
        QXInstrumentViewModel.Instance.Prime(() => { if (abort) throw new RunAbortedException(null); });
    })
    .ContinueWith(task =>
    {
        if (task.IsFaulted)
        {
            if (task.Exception != null && task.Exception.GetBaseException() is RunAbortedException)
            {
                var message = QXInstrumentViewModel.ToErrorCode(ex);
                TokenSource = new System.Threading.CancellationToken(true);
                if (message != null)
                {
                    errorMessage = string.Format((string)TryFindResource("CompletePrimeInstrumentWithError"), Convert.ToInt32(message), errorMessage);
                }
                else
                {
                    errorMessage = (string)TryFindResource("CompletePrimeInstrumentWithUnknownError");
                }
            }
            else
            {
                errorMessage = (string)TryFindResource("CompletePrimeInstrumentAborted");
            }
        }
        cmdDialog?.Close();
        UIUtils.OverrideCursor = null;
        this.IsEnabled = true;
    }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...