我花了整整一天的时间试图让我的应用程序使用线程,但是没有运气。我已经阅读了很多文档,但仍然出现很多错误,因此希望您能对我有所帮助。
我有一个很耗时的方法,它调用数据库并更新GUI。这必须一直发生(或大约每30秒)。
public class UpdateController { private UserController _userController; public UpdateController(LoginController loginController, UserController userController) { _userController = userController; loginController.LoginEvent += Update; } public void Update() { BackgroundWorker backgroundWorker = new BackgroundWorker(); while(true) { backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork); backgroundWorker.RunWorkerAsync(); } } public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { _userController.UpdateUsersOnMap(); } }
通过这种方法,我得到了一个例外,因为backgroundworker不是STA线程(但是据我了解,这是我应该使用的)。我已经尝试过STA线程,但又给出了其他错误。
我认为问题是因为我尝试在进行数据库调用时(在后台线程中)更新GUI。我应该只执行数据库调用,然后以某种方式将其切换回主线程。主线程执行后,应返回到后台线程,依此类推。但是我看不到该怎么做。
在数据库调用之后,应用程序应立即更新GUI。触发事件似乎无效。backgroundthread只是输入它们。
编辑:
一些非常好的答案:)这是新代码:
public class UpdateController{ private UserController _userController; private BackgroundWorker _backgroundWorker; public UpdateController(LoginController loginController, UserController userController) { _userController = userController; loginController.LoginEvent += Update; _backgroundWorker = new BackgroundWorker(); _backgroundWorker.DoWork += backgroundWorker_DoWork; _backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; } public void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { _userController.UpdateUsersOnMap(); } public void Update() { _backgroundWorker.RunWorkerAsync(); } void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //UI update System.Threading.Thread.Sleep(10000); Update(); } public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { // Big database task }
}
但是,如何使它每10秒运行一次呢?System.Threading.Thread.Sleep(10000)只会冻结我的GUI,而建议的Update()中的while(true)循环会出现异常(线程太忙)。
您需要一次声明和配置BackgroundWorker-然后在循环中调用RunWorkerAsync方法。
public class UpdateController { private UserController _userController; private BackgroundWorker _backgroundWorker; public UpdateController(LoginController loginController, UserController userController) { _userController = userController; loginController.LoginEvent += Update; _backgroundWorker = new BackgroundWorker(); _backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork); _backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged); _backgroundWorker.WorkerReportsProgress= true; } public void Update() { _backgroundWorker.RunWorkerAsync(); } public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { while (true) { // Do the long-duration work here, and optionally // send the update back to the UI thread... int p = 0;// set your progress if appropriate object param = "something"; // use this to pass any additional parameter back to the UI _backgroundWorker.ReportProgress(p, param); } } // This event handler updates the UI private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { // Update the UI here // _userController.UpdateUsersOnMap(); } }