this-Me
this-Me

Reputation: 2145

Issues while using BackgroundWorker for Multithreading in MVP

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

Answers (1)

MicroVirus
MicroVirus

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

Related Questions