为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用backgroundworker更新GUI?

如何使用backgroundworker更新GUI?

C#
慕妹3146593 2019-08-19 14:11:01
如何使用backgroundworker更新GUI?我花了一整天的时间试图让我的应用程序使用线程,但没有运气。我已经阅读了很多关于它的文档,我仍然会遇到很多错误,所以我希望你能帮助我。我有一个耗时的方法,它调用数据库并更新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();     }}使用这种方法我得到一个例外,因为后台工作者不是和STA线程(但从我可以理解这是我应该使用的)。我试过一个STA线程,并给出了其他错误。我认为问题是因为我在进行数据库调用时尝试更新GUI(在后台线程中)。我应该只进行数据库调用,然后以某种方式它应该切换回主线程。在主线程执行后,它应该返回后台线程,依此类推。但我看不出怎么做。应用程序应在数据库调用后立即更新GUI。Firering事件似乎不起作用。背景线程只是输入它们
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

您需要声明并配置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();
    }}


查看完整回答
反对 回复 2019-08-19
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

您必须使用Control.InvokeRequired属性来确定您是否在后台线程上。然后,您需要通过Control.Invoke方法调用修改UI的逻辑,以强制UI操作在主线程上发生。您可以通过创建委托并将其传递给Control.Invoke方法来完成此操作。这里的问题是你需要从Control派生的一些对象来调用这些方法。

编辑:当另一个用户发布时,如果您可以等到BackgroundWorker.Completed事件来更新您的UI,那么您可以订阅该事件并直接调用您的UI代码。在主应用程序线程上调用BackgroundWorker_Completed。我的代码假设您希望在操作期间进行更新。我的方法的一个替代方法是订阅BwackgroundWorker.ProgressChanged事件,但我相信在这种情况下你仍然需要调用Invoke来更新你的UI。

例如

public class UpdateController{
    private UserController _userController;        
    BackgroundWorker backgroundWorker = new BackgroundWorker();

    public UpdateController(LoginController loginController, UserController userController)
    {
        _userController = userController;
        loginController.LoginEvent += Update;
    }

    public void Update()
    {                        
         // The while loop was unecessary here
         backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
         backgroundWorker.RunWorkerAsync();                 
    }

    public delegate void DoUIWorkHandler();


    public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
       // You must check here if your are executing on a background thread.
       // UI operations are only allowed on the main application thread
       if (someControlOnMyForm.InvokeRequired)
       {
           // This is how you force your logic to be called on the main
           // application thread
           someControlOnMyForm.Invoke(new             
                      DoUIWorkHandler(_userController.UpdateUsersOnMap);
       }
       else
       {
           _userController.UpdateUsersOnMap()
       }
    }}


查看完整回答
反对 回复 2019-08-19
?
冉冉说

TA贡献1877条经验 获得超1个赞

你应该删除while(true),你正在添加无限的事件处理程序并无限次地调用它们。


查看完整回答
反对 回复 2019-08-19
  • 3 回答
  • 0 关注
  • 469 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信