0

I'm having problems with an AsyncCallback function. I'm using one to download data, and then whatever I do after that, it throws a different exception. Some code:

private void downloadBtn_Click(object sender, RoutedEventArgs e)
{
    string fileName = System.IO.Path.GetFileName(Globals.CURRENT_PODCAST.Title.Replace(" ", string.Empty));
    MessageBox.Show("Download is starting");
    file = IsolatedStorageFile.GetUserStoreForApplication();
    streamToWriteTo = new IsolatedStorageFileStream(fileName, FileMode.Create, file);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(Globals.CURRENT_PODCAST.Uri));
    request.AllowReadStreamBuffering = false;
    request.BeginGetResponse(new AsyncCallback(GetData), request);
}

private void GetData(IAsyncResult result)
{
    HttpWebRequest request = (HttpWebRequest)result.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
    Stream str = response.GetResponseStream();
    byte[] data = new byte[16* 1024];
    long totalValue = response.ContentLength;
    while (str.Read(data, 0, data.Length) > 0)
    {
        if (streamToWriteTo.CanWrite)
            streamToWriteTo.Write(data, 0, data.Length);
        else
            MessageBox.Show("Could not write to stream");
    }
    streamToWriteTo.Close();
    MessageBox.Show("Download Finished");
}

Is there any way to tell when an async callback has finished, and then run code without crashing, or something I am doing wrong here?

Patrick D'Souza
  • 3,491
  • 2
  • 22
  • 39
AllFallD0wn
  • 551
  • 7
  • 23
  • You're definitely doing something wrong there. Your read/write loop will potentially write too much data. For example, your loop always writes in blocks of 16 kilobytes. So even if you only download 23 bytes, a full 16 KB will be written. Furthermore, you never close the response or the response stream. That's almost certainly going to cause problems. You'll need to tell us what exceptions you're getting if you want more specific recommendations. – Jim Mischel Nov 15 '12 at 05:03
  • I end the get response, if that's what you mean?: HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); – AllFallD0wn Nov 15 '12 at 12:47
  • Look into `HttpWebResponse.Close` and `Stream.Close`. – Jim Mischel Nov 15 '12 at 13:15
  • Just tried those two, and it's still erroring on the MessageBox.Show, with the exception: "An exception of type 'System.UnauthorizedAccessException' occurred in System.Windows.ni.dll but was not handled in user code" – AllFallD0wn Nov 15 '12 at 13:25
  • Is the problem that you're calling `MessageBox.Show` from a threadpool thread? In general, you want to do that on the GUI thread. What happens if you remove the call to `MessageBox.Show`? – Jim Mischel Nov 15 '12 at 14:44
  • If I don't do the MessageBox.Show, it finishes the thread fine, but I want some kind of "This has finished" notification for the user afterwards? – AllFallD0wn Nov 15 '12 at 15:46

1 Answers1

2

The problem is that you're calling MessageBox.Show from a threadpool thread. You need to call it from the UI thread. To do that, you need to synchronize with the UI thread. For example:

this.Invoke((MethodInvoker) delegate
    { MessageBox.Show("success!"); });

The call to Invoke will execute the code on the UI thread. See documentation for Control.Invoke for more information.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • The theory behind what was wrong was correct, and was I using a forms app, this would have been perfect, so I've marked right answer. Actual code to fix was (Windows Phone 7): Dispatcher.BeginInvoke(delegate { ShowCompletionMessage(); }); -- Thanks a lot! – AllFallD0wn Nov 15 '12 at 17:43