一尘不染

如何使用backgroundworker更新GUI?

c#

我花了整整一天的时间试图让我的应用程序使用线程,但是没有运气。我已经阅读了很多文档,但仍然出现很多错误,因此希望您能对我有所帮助。

我有一个很耗时的方法,它调用数据库并更新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)循环会出现异常(线程太忙)。


阅读 261

收藏
2020-05-19

共1个答案

一尘不染

您需要一次声明和配置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();
    }
}
2020-05-19