我一直在尝试在我的MVP代码中引入多线程来在UI线程上移除负载,以便在工作线程在后台执行长时间运行的操作时可以自由地向用户执行/显示进度通知。
在View中显示实现: 类CalculationView(view)中的eventhandler在CalculationPresenter(演示者)上调用长时间运行的操作
这样的事情:
private void btnCalculate_Click(object sender, EventArgs e)
{
mPresenter.PerformLongRunningTask();
}
现在,为了介绍多线程,我打算使用BackgroundWorker在演示者中调用PerformLongRunningTask
构造函数中的BackgroundWorker初始化代码
//Member declaration
BackgroundWorker m_oWorker; //Backgroundworker thread
ProgressDialog dialog; //A simple wait dialog
..
//constructor
..
m_oWorker = new BackgroundWorker();
m_oWorker.DoWork += DoLongRunningWork;
m_oWorker.RunWorkerCompleted += LongRunningWorkCompleted;
现在,我想使用BackgroundWorker线程调用PerformLongRunningTask方法,以便我可以显示UI表单(等待对话框)。 我的BackgroundWorker无需支持取消或报告进度。因此,我在初始化BackgroundWorker线程时没有设置这些属性。
private void btnCalculate_Click(object sender, EventArgs e)
{
if(m_oWorker !=null)
{
dialog = new ProgressDialog(); //initialize wait dialog
dialog.Show(); //Display wait dialog
m_oWorker.RunWorkerAsync(); //Invoke BackgroundWorker thread
}
}
//Calls the LongRunning task in the background
void DoLongRunningWork(object sender, DoWorkEventArgs e)
{
mPresenter.PerformLongRunningTask();
}
//Closes the progress dialog displayed on the UI after completion
void LongRunningWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(dialog != null) dialog.Close()
}
但是,根据上述代码,我无法实现我想要做的事情。在演示者代码中引用View类会引发跨线程异常。
"Cross-thread operation not valid: Control 'cmbSelect' accessed from a thread other than the thread it was created on."
即使在长时间运行操作完成执行之前,等待对话框就会出现并关闭。
任何建议/模式,以便正确访问演示者内部引用视图类的控件。 (例如:Control.InvokeRequired)在Presenter代码中?
答案 0 :(得分:1)
评论中的解决方案,以帮助未来的读者
一旦事件处理程序DoLongRunningWork
返回,工作人员就会认为其工作已完成。在函数中设置断点,看看会发生什么。
同时查看Error
的{{1}}属性是否已设置:如果是,则工作线程抛出未处理的异常,导致后台工作者返回/取消。