1

This is my code:

foreach (var pathCartella in folderList)
{
    try
    {
        // some operation

        if (txtMonitor.InvokeRequired)
        {
            txtMonitor.BeginInvoke(new MethodInvoker(delegate { txtMonitor.AppendText(pathCartella + Environment.NewLine); }));
        }
    }
    catch (Exception err)
    {
        // some operation
        return;
    }
}

but I notice that, if I catch an Exception, return can act before that all txtMonitor.InvokeRequired has been sent to the UI, and I lost some "message".

How can I avoid this?

markzzz
  • 47,390
  • 120
  • 299
  • 507
  • 2
    If you always want the code in the `if` statement to run, can you not move the call to a `finally` block? – dash Apr 19 '13 at 07:15
  • Uhm, not sure about what you mean! Can you give to me an example? – markzzz Apr 19 '13 at 07:16
  • You are trying to put a band-aid on a pretty serious wound in your program. There's no guarantee that your try/catch is going to stop the bleeding. Trying to use a finally block makes it a **lot** worse. Check [this answer](http://stackoverflow.com/a/1732361/17034) for a real fix. – Hans Passant Apr 19 '13 at 09:03
  • @HansPassant: honestly I can't figure it out why this configuration can going to hell. Can you give to me an example of this scenario will totally go wrong? – markzzz Apr 19 '13 at 09:08
  • You are invoking to a window that isn't around anymore. The runtime told you about that problem and you shut it up by catching the exception. That kinda worked but now you got a new problem, that happens when you shoot the messenger. Address the real problem, the thread needs to stop running when the user wants to quit your program. Reproduce it by closing the window while the thread is still running. – Hans Passant Apr 19 '13 at 09:48
  • Uhm, but this I think is the basic of Thread. My Thread is working, putting message to the UI till I have a problem (catch). When it catch it, I stop the thread with "return". That's not wrong I believe. Ok, if I close the UI and the thread are running, ok! But that's another problem, not related to this one, and I hope it is managed by Task.Factory, isnt it? – markzzz Apr 19 '13 at 10:10

1 Answers1

4

If I understand your requirements correctly, then you can use the third part of the try/catch block - finally

The finally block is useful for cleaning up any resources allocated in the try block. Control is always passed to the finally block regardless of how the try block exits. This statement takes the following form:

So your code would change to something of the form:

foreach (var pathCartella in folderList)
{
    try
    {
        // some operation


    }
    catch (Exception err)
    {
        // some operation
        return;
    }
    finally
    {
        if (txtMonitor.InvokeRequired)
        {
            txtMonitor.BeginInvoke(new MethodInvoker(delegate { txtMonitor.AppendText(pathCartella + Environment.NewLine); }));
        }
    }
}

A couple of notes - are you sure you only want to run it if InvokeRequired is true? If you are running it from a simple button click, for example, and not from a background thread, then InvokeRequired will be false and code will never execute.

If you are wondering about whether finally will always be called, then this particular question has been asked many times. See If I return out of a try/finally block in C# does the code in the finally always run? for example. That has some interesting counter-examples.

The other option you could consider is to simply throw your exception. You could pass pathCartella as part of the error message, so you know what path the exception happened on, and what the exception was. Your caller can then handle this. For example:

foreach (var pathCartella in folderList)
{
    try
    {
        // some operation


    }
    catch (Exception err)
    {
        // some operation

        //The original exception becomes the inner exception (so you can get original
        //error and stack trace etc). The new exception message contains the path.
        throw new Exception(
            String.Format("Failed to perform operation on '{0}'", pathCartella), 
            err);

    }

}
Community
  • 1
  • 1
dash
  • 89,546
  • 4
  • 51
  • 71
  • I'm in a separate thread, not the one in the UI. I want to print ALL messagges in the txtMonitor until I get an exception. – markzzz Apr 19 '13 at 07:22
  • That should do it then. Finally will execute everytime, in the case of your exception, it will still run, but it will be the last pathCartella processed. – dash Apr 19 '13 at 07:24
  • I don't know why, but putting finally seems that foreach continue all iteration, also if I put a "break" :O Suppose I have 100 iteration, and the first 80 are ok. 81° I get an exception: finally will be executed 81 times, right? – markzzz Apr 19 '13 at 07:58
  • Yes, that is what should happen - it will run for each iteration, until the last one, when finally will run, but then it will return so that will be the last "loop" – dash Apr 19 '13 at 08:24