阻止UI线程不会呈现其他窗口的UI组件

时间:2019-01-07 20:09:59

标签: c# wpf multithreading

在我的应用程序中,我有一种情况,当我执行操作时需要阻止UI线程。当它被阻止时,我有另一个窗口,当用户界面被阻止时,需要显示一条消息,提示“请执行操作,请稍候”。问题是出现了窗口,但从未显示该消息。请帮忙。甚至DoEvents()也无济于事。它只是轻轻地显示消息

注意:

  1. 我不希望该方法异步,因为我想在UI运行时阻止它。
  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具有绑定到文本块的字符串(消息)类型的依赖项属性。

1 个答案:

答案 0 :(得分:-1)

您不能同时在同一线程上阻止和显示消息。

您应该做的是在后台线程上执行长时间运行的操作-最简单的方法是启动TPL task-在UI线程上显示消息。您仍然可以禁用该窗口。只要确保您不要触摸长时间运行操作执行的后台线程上的UI。

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());
}