Reputation: 2145
I have been trying to introduce multithreading in my MVP code to shift the load off on the UI thread so that it is free to perform/display progress notification to the user while the worker thread is executing a long running operation in the background.
Present implementation inside View: The eventhandler inside class CalculationView (view) invokes a long running operation on CalculationPresenter (presenter)
Something like this:
private void btnCalculate_Click(object sender, EventArgs e)
{
mPresenter.PerformLongRunningTask();
}
Now, To introduce multithreading, I plan to use BackgroundWorker to call the PerformLongRunningTask in the presenter
Initialization code of BackgroundWorker in the Constructor
//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;
Now, I want to call the PerformLongRunningTask method using BackgroundWorker thread, so that I can display a UI form (wait dialog). My BackgroundWorker need not support cancellation or report progress. Hence I'm not setting those properties while initializing BackgroundWorker thread.
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()
}
However, with the above code I'm not able to achieve what I'm trying to do. A reference of View class inside the presenter code is throwing cross-thread exception.
"Cross-thread operation not valid: Control 'cmbSelect' accessed from a thread other than the thread it was created on."
Due to which the wait dialog simply appears and closes even before the long running operation has completed its execution.
Any suggestions/pattern to properly access the controls inside the presenter having reference to the view class. (ex: Control.InvokeRequired) in the Presenter code ?
Upvotes: 0
Views: 80
Reputation: 5477
The solution from the comments, to help future readers
The worker considers its work done as soon as the event handler, DoLongRunningWork
here, returns. Set a breakpoint in the function and see what happens.
Also see if the Error
property of the RunWorkerCompletedEventArgs
is set: if so, then the worker thread threw an exception that went unhandled, causing your backgroundworker to return/cancel.
Upvotes: 1