我有一个程序需要10-20秒才能启动。我需要在程序启动时显示一个带有进度条的窗口。我知道BackgroundWorker是正确的方法,但我很遗憾没有时间使用线程重做整个gui。这是我正在尝试的一些代码,但它不起作用。谁能帮忙..?
using System;
using System.Threading;
using System.Windows;
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
Thread t = new Thread(ShowLoadingWindow);
t.SetApartmentState(ApartmentState.STA);
t.Priority = ThreadPriority.Highest;
t.Start();
DoSomeLongTask();
keepLooping = false;
}
bool keepLooping = true;
private void ShowLoadingWindow()
{
LoadingWindow lw = new LoadingWindow();
lw.Show();
while (keepLooping)
{
Thread.Sleep(1);
}
lw.Close();
}
private void DoSomeLongTask()
{
for (int i = 0; i < 20000; i++)
{
GC.Collect();
}
}
}
}
加载窗口只是一个带有进度条的裸窗口。如果这不起作用?
答案 0 :(得分:10)
你仍然在主线程中完成长任务。您需要在主线程中显示加载窗口,并在后台执行长任务。
使用BackgroundWorker确实是最简单的解决方案:
BackgroundWorker bw; LoadingWindow lw; public Window1() { bw = new BackgroundWorker(); lw = new LoadingWindow(); bw.DoWork += (sender, args) => { // do your lengthy stuff here -- this will happen in a separate thread ... } bw.RunWorkerCompleted += (sender, args) => { if (args.Error != null) // if an exception occurred during DoWork, MessageBox.Show(args.Error.ToString()); // do your error handling here // close your loading window here ... } // open and show your loading window here ... bw.RunWorkerAsync(); // starts the background worker }
答案 1 :(得分:5)
使用backgroundworker非常容易。
public partial class Window1 : Window
{
BackgroundWorker worker = new BackgroundWorker();
public Window1()
{
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ReportsProgress = true;
worker.ProgressChanged += new ProgressChangedEventHandler(update_progress);
}
void worker_DoWork(object sender, DoWorkEventArgs e){
DoSomeLongTask();
//call worker.ReportProgress to update bar
}
void update_progress(object sender, ProgressChangedEventArgs e)
{
myscrollbar.Value = e.Value;
}
}
要记住的关键是永远不要触摸DoWork方法中的gui东西。这必须通过ProgressChanged / ReportProgress
答案 2 :(得分:3)
如果您不想要后台工作程序,则需要调整代码,以便在新线程中执行长任务。
using System;
using System.Threading;
using System.Windows;
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
Thread t = new Thread(DoSomeLongTask);
t.Start();
// switch this with the DoSomeLongTask, so the long task is
// on the new thread and the UI thread is free.
ShowLoadingWindow();
}
}
}
如果您想从“DoSomeLongTask”方法更新进度条,则需要确保调用invoke。例如:
delegate void ProgressDelegate(int Progress);
private void UpdateProgress( int Progress)
{
if (!progressBar1.Dispatcher.CheckAccess())
{
progressBar1.Value = Progress;
}
else
{
ProgressDelegate progressD = new ProgressDelegate(UpdateProgress);
progressBar1.Dispatcher.Invoke(progressD, new object[] { Progress });
}
}