1

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

我已经按照Reed Copsey 的这个例子实现了我的解决方案。

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

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

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

2 回答 2

0

也许您应该考虑使用 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();
}
于 2012-10-18T11:11:26.820 回答
0

What you should do is encapsulate your operation within its own class, and make it raise an event when it's completed (or you want to close the view)

The event handler will need to use the Dispatcher to run the close() in the same thread as the view.

于 2012-10-18T11:03:34.980 回答