views:

327

answers:

2

hello. I have a try-catch statement in reference to downloading a file. When the file is downloaded, I then enable one of my menu items then turn off a timer set to retry the download in one minute.

My problem is that for some reason my "trafficManagementToolStripMenuItem.Enabled = true;" line is activating the catch statement even though, the menu item is being enabled. The file correctly downloads and when I comment out that line, it works perfectly. But every time I run it, i get the "error" message box and the timer is not disabled. Even though the menu item correctly enables after the download is complete.

any ideas?

try
{
    ////downloads Data

    string address = "http://website.file.txt";
    string filename = "vsd.txt";
    WebClient client = new WebClient();
    client.DownloadFile(address, filename);
    trafficManagementToolStripMenuItem.Enabled = true;
    timer1.Enabled = false;
}
catch
{
    timer1.Enabled = true;
    MessageBox.Show("error", "test");
}
+4  A: 

You don't say what the exception is, but I'd guess that you're running your download routine in a background thread, is that right? You can only access controls from the thread that created them: the main UI thread. Accessing a control such as a ToolStripMenuItem from a background thread will cause an exception.

If this is the case, use the Control.Invoke or Control.BeginInvoke method to run the .Enabled = true call on the ToolStripMenuItem's thread. To do this, you'll need a Control (unfortunately ToolStripMenuItem is only a Component). I'll assume you can get a reference to the containing Form from somewhere. Now you can write this:

Action enableAction = delegate() { trafficManagementToolStripMenuItem.Enabled = true; }
form.BeginInvoke(enableAction);

This causes the enableAction to run on the correct UI thread for form.

itowlson
I'm using my psychic powers to predict itowlson's pychic debugging will fix the issue.
RedDeckWins
*Never* use Invoke. Always BeginInvoke.
wj32
"Never" is too strong. But you're right, it's good to get into the habit of using BeginInvoke unless there's a specific reason to prefer Invoke. I'll update the example.
itowlson
+4  A: 

change your catch to be

catch (Exception ex) 
{ 
    timer1.Enabled = true; 
    MessageBox.Show("error", ex.Message); 
}

This will at least give you the actual error message.

I'm guessing it's because you are not running in the UI thread and need to use Control.Invoke, take a look at http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx on msdn

Bob Vale
i've read the link and understand the problem, but I'm just too new at this to understand what I need to do to make it work on the first try.
Brodie
-1: Do not use ex.Message, use ex.ToString().
John Saunders
try this....Action action=new Action(()=>{trafficManagementToolStripMenuItem.Enabled = true;timer1.Enabled = false; };if (trafficManagementToolStripMenuItem.InvokeRequired) { trafficManagementToolStripMenuItem.Invoke(action);} else { action();}
Bob Vale