1

I have this code in a button click

private async void btnStart_Click(object sender, EventArgs e)
    {
        Msg.Clear();
        stopWatch.Reset();
        timer.Start();
        stopWatch.Start();
        lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
        progressBar.MarqueeAnimationSpeed = 30;
        try
        {
            await Task.Factory.StartNew(() =>
             {
                 try
                 {
                     Reprocess();
                 }
                 catch (Exception ex)
                 {
                     Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
                     timer.Stop();
                     stopWatch.Stop();
                     throw;
                 }
             });
        }
        catch
        {
            throw;
        }
    }

and this on the Reprocess method

private void Reprocess()
    {
        try
        {
            clsReprocess reprocess = new clsReprocess(tbBD.Text, dtpStart.Value, 50000);
            reprocess.Start(reprocess.BD);
        }
        catch
        {
            throw;
        }
    }

when the Reprocess method fails, the Task goes to catch, but the throw fails (the throw inside catch (Exception ex)) and the UI blocks until the reprocess.Start method is completed. I have two questions:

  • First: How can I catch the throw in the catch of my button?
  • Second: How can I prevent the UI blocks?

I hope you can understand me, sorry for my bad english.

  • Why did you insert those `catch` handlers that do nothing? I always wondered why people are doing this hence I'm asking. – usr Feb 09 '16 at 22:34
  • @usr http://stackoverflow.com/questions/8009773/using-catch-without-arguments – Gabe Feb 09 '16 at 22:38
  • I'm catching the error (on the Task) for show in a DatagridView, the problem is that the system continues doing the Reprocess method, after that catch – Abdel Posada Feb 09 '16 at 22:39
  • System catch an exception (on reprocess.Start(reprocess.BD)) – Abdel Posada Feb 09 '16 at 22:45
  • @Gabe what I mean is: Why catch and rethrow immediately? This never does anything. – usr Feb 09 '16 at 22:46
  • @usr ahh sorry my mistake, long day. That's enough internet for me – Gabe Feb 09 '16 at 23:02
  • 1
    Please cleanup your code, get rid of unnecessary `try .. catch { throw; }` blocks, use `Task.Run` instead of `Task.Factory.StartNew`, move your `catch (Exception ex) {...}` block below the `await`, and don't EVER access any UI controls from a background thread. – Yarik Feb 10 '16 at 00:02
  • It's counterproductive to give direct instructions without reasoning. Try explaining _why_ the OP should do it? Educate, not humiliate. – Gabe Feb 10 '16 at 00:40

1 Answers1

1

You should not use Task.Factory.StartNew; Task.Run is both safer and shorter to write.

Also, you can only access UI controls from the UI thread. This may be the cause of the problems you're seeing, if Msg is data-bound to the UI. Even if it's not, you don't want to access unprotected collections (e.g., List<clsMSG>) from multiple threads.

Applying both of these guidelines reduces the code to:

private async void btnStart_Click(object sender, EventArgs e)
{
  Msg.Clear();
  stopWatch.Reset();
  timer.Start();
  stopWatch.Start();
  lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
  progressBar.MarqueeAnimationSpeed = 30;
  try
  {
    await Task.Run(() => Reprocess());
  }
  catch (Exception ex)
  {
    Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
    timer.Stop();
    stopWatch.Stop();
    throw;
  }
}

If Reprocess throws an exception, that exception will be placed on the task returned from Task.Run. When your code awaits that task, that exception is re-raised and caught in the catch. At the end of the catch, the code will re-raise that exception (throw;).

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810