我想在运行耗时的任务时显示一个带有Indeterminate="True"
进度条的简单WPF窗口。
我在this示例之后实施了我的解决方案 - Reed Copsey。
一旦完成该过程,我需要关闭窗口。 我的猜测是要实现这一点,我要么要杀死线程要么关闭视图(窗口)。
不幸的是,两种方式都会给我以下错误:
1)在线程上调用Abort()
:
窗口关闭,这是正确的,但我仍然收到以下错误:
无法评估表达式,因为代码已优化或本机框位于调用堆栈之上
2)View.Close()
:
调用线程无法访问此对象,因为另一个线程拥有它。
需要在StopThread()
方法中实现所需的逻辑,知道如何优雅地关闭Window:
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();
}
}
}
答案 0 :(得分:0)
您应该做的是将您的操作封装在自己的类中,并在事件完成时(或者您想要关闭视图)引发事件
事件处理程序需要使用Dispatcher
在与视图相同的线程中运行close()
。
答案 1 :(得分: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();
}