我目前正在编写一个GUI程序,可以完成一些工作并在之后退出。工作完成后,GUI线程将使用信息为用户更新。
这是我目前正在使用的模式,我认为这不是最优雅的模式:
static void MainForm_Loaded(BeoExport exporter)
{
// Thread 1 runs the Export
workerThread = new Thread(() =>
{
exporter.StartExport();
// don't exit immediately, so the user sees someting if the work is done fast
Thread.Sleep(1000);
});
// Thread 2 waits for Thread 1 and exits the program afterwards
waiterThread = new Thread(() =>
{
workerThread.Join();
Application.Exit();
});
workerThread.Start();
waiterThread.Start();
}
那么你会用什么模式/机制来做同样的事情?
澄清一下:我对更新GUI线程的方式不感兴趣。那已经完成了。这可能听起来很深奥,但我很想找到退出应用程序的正确方法。
如果可以的话,我会给予Dave学分,因为他指出了BackgroundWorker的用处。
答案 0 :(得分:2)
您是否考虑过BackgroundWorker
线程?您可以使用其ReportProgress
方法和ProgressChanged
事件更新GUI(可能包含进度条),假设您可以重构BeoExport.StartExport
方法以报告进度。这为用户提供了实际工作正在发生的可见反馈。
答案 1 :(得分:2)
我不明白你为什么要使用两个线程。你可以使用threadpool:
ThreadPool.QueueUserWorkItem((state)=>{
exporter.StartExport();
Thread.Sleep(1000);
Application.Exit();
});
答案 2 :(得分:2)
我建议您使用BackgroundWorker课程。它被认为是做你正在做的那种工作。你可以这样做:
public class Form1 : Form
{
private BackgroundWorker worker;
private ProgressBar bar;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
bar= new ProgressBar();
bar.Dock = DockStyle.Top;
Controls.Add(bar);
worker = new BackgroundWorker();
worker.WorkerReportsProgress=true;
worker.RunWorkerCompleted += delegate
{
Close();
};
worker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs ev)
{
bar.Value = ev.ProgressPercentage;
};
worker.DoWork += worker_DoWork;
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
//do your work here. For the example, just sleep a bit
//and report progress
for (var i = 0; i < 100;i++ )
{
Thread.Sleep(50);
worker.ReportProgress(i);
}
}
}
答案 3 :(得分:1)
您可以使用AutoResetEvent。主线程等待重置autoreset事件。
var wh = new AutoResetEvent(false);
var workerThread = new Thread(() =>
{
exporter.StartExport();
// don't exit immediately, so the user sees something if the work is done fast
Thread.Sleep(5000);
wh.Set();
});
workerThread.Start();
wh.WaitOne();
Application.Current.Shutdown();
答案 4 :(得分:1)
答案 5 :(得分:1)
为Lain的回答添加一点,这是使用System.Threading.Tasks命名空间中的任务的控制台示例。
class Program
{
static void Main(string[] args)
{
Task<int> task = Task<int>.Factory.StartNew(() =>
{
Exporter exporter = new Exporter();
int i = exporter.StartExport();
return i;
});
int iResult = task.Result;
Console.WriteLine(iResult);
Console.ReadLine();
}
class Exporter {
public int StartExport()
{
//simulate some work
System.Threading.Thread.Sleep(500);
return 5;
}
}
}
答案 6 :(得分:1)
使用BackgroundWorker
可能会帮助您实施后台处理。如果您想坚持使用当前模式,请考虑以下内容。
static void MainForm_Loaded(BeoExport exporter)
{
workerThread = new Thread(() =>
{
exporter.StartExport();
Thread.Sleep(1000);
MainForm.BeginInvoke(
(Action)(() =>
{
MainForm.Close();
});
});
workerThread.IsBackground = true;
workerThread.Start();
}
答案 7 :(得分:0)
让工作线程向主线程发送一些描述的通知消息。然后,GUI可以根据需要退出或显示“完成”消息。