在 MVP 中使用后台工作线程进行多线程处理时出现问题
本文关键字:多线程处理 问题 线程 MVP 工作 后台 | 更新日期: 2023-09-27 18:36:56
我一直在尝试在我的 MVP 代码中引入多线程以转移 UI 线程上的负载,以便在工作线程在后台执行长时间运行的操作时可以自由地向用户执行/显示进度通知。
在视图中呈现实现:类 ComputeView(视图)中的事件处理程序调用计算呈现器(表示器)上的长时间运行的操作
像这样:
private void btnCalculate_Click(object sender, EventArgs e)
{
mPresenter.PerformLongRunningTask();
}
现在,为了引入多线程,我计划使用 BackgroundWorker 在表示器中调用 PerformLongRunningTask
构造函数中后台工作者的初始化代码
//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 窗体(等待对话框)。我的后台工作者不需要支持取消或报告进度。因此,我在初始化后台工作线程时不会设置这些属性。
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."
因此,等待对话框甚至在长时间运行的操作完成其执行之前就简单地出现和关闭。
正确访问表示器内部引用视图类的控件的任何建议/模式。 (例如:控件.调用必需) 在演示器代码中?
从评论中解脱出来,帮助未来的读者
一旦事件处理程序(此处DoLongRunningWork
)返回,工作线程就会认为其工作已完成。在函数中设置断点,看看会发生什么。
另请查看是否设置了 RunWorkerCompletedEventArgs
的 Error
属性:如果是这样,则工作线程抛出一个未处理的异常,导致后台工作线程返回/取消。