0

I recently started working with WinForms via MVP (PassiveView) pattern and stuck on
"How to make View update itself while presenter does long (for like 20 seconds) async operations"

So I have a form, an IView implementation with UI items:

  • a Button on which my presenter is subscribed to via Click event;
  • a DataGridView with a checkbox column;
  • A ProgressBar;
  • and two fields. Current and SelectedCount;

So what am I doing there?
On that Click, my Presenter grabs "checked" items from datagrid and writes them to database.
Since that processing takes time, I made this method async:

private async void PutToDatabase(List<Item> items)
{
    View.SelectedCount = items.Count;
    for (int i = 0; i < items.Count; i++)
    {
        await Task.Factory.StartNew(
         () =>
            {
                // writing stuff to database via ADO.NET
                View.Current = i;
            });
    }
}

So I am updating my Current, which updates my progressBar by doing this:

public int CurrentPrice
{
    get { return _current; }
    set
    {
        _current = value;
        Invoke((MethodInvoker) delegate {progBarImportState.Value = _current; });
    }
}

I'm not sure, if this approach is going to work fine, since I can't reload my UI to use the form again, unless I gonna check somwhere (e.g. in the same delegate) if progress.value == progress.maximum and rollback the form to reuse it. Plus, it doesn't look 'pretty'.

So are there any more effective/cleaner solution than this?

Kirill F.
  • 159
  • 1
  • 6

1 Answers1

0

Why don't you use Back ground workers, pretty old school but woks good. Click here for more info on Background Workers. You can use the Background-Worker like this:

private void Main(string[] args)
{
    BackgroundWorker bw = new BackgroundWorker();
    bw.DoWork += Bw_DoWork;
    bw.RunWorkerCompleted += Bw_RunWorkerCompleted;

    //Parameter you need to work in Background-Thread for example your strings
    string[] param = new[] {"Text1", "Text2", "Text3", "Text4"};

    //Start work
    bw.RunWorkerAsync(param);
}

//Do your Background-Work
private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
    string[] param = e.Argument as string[];

    //Process your long running  task

    e.Result = null; //Set your Result of the long running task
}

//Taking your results
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //Apply your Results to your GUI-Elements
    myTextBox1.Text = e.Result.ToString();
}
Tom J
  • 1
  • 1
  • 2
  • As you may see I'm already using `Task`s within Presenter and updating Model's field in it. If you're suggesting to use BGW in a View, it kinda hangs the UI. – Kirill F. May 30 '18 at 14:58