如何使用后台工作人员更新 GUI? [英] How to update GUI with backgroundworker?

查看:24
本文介绍了如何使用后台工作人员更新 GUI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了一整天的时间试图让我的应用程序使用线程,但没有成功.我已经阅读了很多关于它的文档,但仍然有很多错误,所以我希望你能帮助我.

I have spent the whole day trying to make my application use threads but with no luck. I have read much documentation about it and I still get lots of errors, so I hope you can help me.

我有一个非常耗时的方法,它调用数据库并更新 GUI.这必须一直发生(或大约每 30 秒一次).

I have one big time consuming method which calls the database and updates the GUI. This has to happen all the time(or about every 30 seconds).

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 线程,但出现了其他错误.

With this approach I get an exception because the backgroundworker is not and STA thread(but from what I can understand this is what I should use). I have tried with a STA thread and that gave other errors.

我认为问题是因为我在执行数据库调用时(在后台线程中)尝试更新 GUI.我应该只做数据库调用,然后它应该以某种方式切换回主线程.主线程执行完毕后,它应该返回到后台线程,依此类推.但我不知道该怎么做.

I think the problem is because I try to update the GUI while doing the database call(in the background thread). I should only be doing the database call and then somehow it should switch back to the main thread. After the main thread has executed it should go back to the background thread and so on. But I can't see how to do that.

应用程序应在调用数据库后立即更新 GUI.触发事件似乎不起作用.后台线程只是进入它们.

The application should update the GUI right after the database call. Firering events don't seem to work. The backgroundthread just enters them.

一些非常好的答案:) 这是新代码:

Some really great answers :) This is the new code:

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) 循环按照建议给出一个异常(线程太忙).

But how can I make this run every 10 second? System.Threading.Thread.Sleep(10000) will just make my GUI freeze and while(true) loop in Update() as suggested gives an exception(Thread too busy).

推荐答案

您需要声明和配置一次 BackgroundWorker - 然后在您的循环中调用 RunWorkerAsync 方法...

You need to declare and configure the BackgroundWorker once - then Invoke the RunWorkerAsync method within your loop...

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();
    }
}

这篇关于如何使用后台工作人员更新 GUI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆