【问题标题】:Displaying WPF ProgressBar window in separate thread在单独的线程中显示 WPF ProgressBar 窗口
【发布时间】:2012-10-18 22:47:34
【问题描述】:

我想在运行耗时的任务时显示一个带有Indeterminate="True" 进度条的简单 WPF 窗口。

我已经按照 Reed Copsey 的 this 示例实施了我的解决方案。

该过程完成后,我需要关闭窗口。 我的猜测是,要实现这一点,我需要终止线程或关闭视图(窗口)。

不幸的是,两种方式都给我以下错误:

1)在线程上调用Abort()

窗口已关闭,这是正确的,但我仍然收到以下错误:

无法评估表达式,因为代码已优化或本机框架位于调用堆栈顶部

2)View.Close():

调用线程无法访问此对象,因为另一个线程拥有它。

需要在StopThread() 方法中实现所需的逻辑,知道我可以做什么来优雅地关闭窗口:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using Microsoft.Practices.Composite.Presentation.Commands;

namespace ProgressBar
{
    public class ProgressBarViewModel
    {
        public DelegateCommand<object> CloseCommand { get; set; }
        Thread newWindowThread;

        string _closeButton;
        public string CloseButton 
        {
            get { return _closeButton; }
            set { _closeButton = value; }
        }

        ProgressBarView _view;
        public ProgressBarView View
        {
            get { return _view; }
            set { _view = value; }
        }

        public ProgressBarViewModel(ProgressBarView view)
        {
                CloseButton = "Close";
                CloseCommand = new DelegateCommand<object>(CloseForm);

                View = view;
                View.Closing +=new System.ComponentModel.CancelEventHandler(View_Closing);
                View.DataContext = this;
        }

        public void View_Closing(object sender,CancelEventArgs e)
        {
            StopThread();
        }

        public void CloseForm(object p)
        {
            StopThread();
        }

        private void StopThread()
        {
            try
            {
                //View.Close();
                newWindowThread.Abort();
            }
            catch (Exception eX)
            {
                Debugger.Break();
                //Getting an error when attempting to end the thread:
                //Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack
            }
        }

        public void ShowProgress()
        {
                newWindowThread = new Thread(new ThreadStart(() =>
                {
                    ProgressBarView tempWindow = new ProgressBarView();
                    tempWindow.DataContext = this;
                    tempWindow.Show();
                    System.Windows.Threading.Dispatcher.Run();
                }));

                newWindowThread.SetApartmentState(ApartmentState.STA);
                newWindowThread.IsBackground = true;
                newWindowThread.Start();
        }
    }
}

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    你应该做的是将你的操作封装在它自己的类中,并在它完成时引发一个事件(或者你想关闭视图)

    事件处理程序需要使用Dispatcher 在与视图相同的线程中运行close()

    【讨论】:

      【解决方案2】:

      也许您应该考虑使用 BackgroundWorker 进行此操作?您可以响应 RunWorkerCompleted 事件来关闭视图。

      public void YourFunction(Dispatcher dispatcher)
      {
          BackgroundWorker bw = new BackgroundWorker();
          bw.DoWork += (sender, args) =>
            {
               ...do your long running operation
            };
      
          bw.RunWorkerCompleted += (sender, args) =>
            { 
               dispatcher.BeginInvoke(...close your view here);
            }
      
          bw.RunWorkerAsync();
      }
      

      【讨论】:

      • 试一试,得到与我尝试调用 View.Close(); 时相同的错误;还有其他想法吗?
      • @Deni...您是否正在调试发布版本(“代码已优化”)?这可能与 Visual Studio 有关。
      • @Deni...如果 BGW 不是在 UI 线程上创建的,那么您需要传入 Dispatcher 并关闭您的视图。您是否触发了 RunWorkerCompleted 事件?
      猜你喜欢
      • 2020-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-27
      • 1970-01-01
      • 1970-01-01
      • 2020-11-26
      相关资源
      最近更新 更多