0

So in my app I have a button that talks to a lib that downloads some data from the internet and filters it. When the app is doing this the screen freezes and it looks to the user like the app crashed. But this is not the case because its downloading data.

Here is my code:

GetDetailsBtn.TouchUpInside += (sender, e) => {

    var defaults = NSUserDefaults.StandardUserDefaults;

    if (RefNr.Text != string.Empty && RefNr.Text != null) {

        FilteredDataRef = _FetchingData.getTrackTraceData (defaults.StringForKey ("SecurityToken"), RefNr.Text);

        if (FilteredDataRef == null) {
            UIAlertView InvalidAlert = new UIAlertView ("Reference number invalid", "The reference number that you have entered is not linked to the current security code. You can change your security code in the settings.", null, "OK", null);
            InvalidAlert.Show ();

        } else {
            FilteredDataReceived = _FetchingData.FilteringOnReceived (FilteredDataRef);

            FilteredDataPlanned = _FetchingData.FilteringOnPlanned (FilteredDataRef);

            FilteredDataLoadingETA = _FetchingData.FilteringOnLoadingETA (FilteredDataRef);

            FilteredDataLoadingFinal = _FetchingData.FilteringOnLoadingFinal (FilteredDataRef);

            FilteredDataUnloadingETA = _FetchingData.FilteringOnUnloadingETA (FilteredDataRef);

            FilteredDataUnloadingFinal = _FetchingData.FilteringOnUnloadingFinal (FilteredDataRef);   

            this.PerformSegue (MoveToTrackTraceDetailsSegue, this);

            //foreach (string s in FilteredDataPlanned)
            //    Console.WriteLine (s);

        }

    } else {
        UIAlertView InvalidAlert = new UIAlertView ("Reference number cannot be empty", "You did not provide a reference number. We need your reference number to trace identify the shipment you would like to trace.", null, "OK", null);
        InvalidAlert.Show ();
    }
};

Downloading of the data:

public IEnumerable<string> getTrackTraceData (string securityCode, string referenceNumber)
{
    WebRequest request = WebRequest.Create ("http://plex.janssen1877.com/app/life/" + securityCode);

    HttpWebResponse response = (HttpWebResponse)request.GetResponse ();

    Stream dataStream = response.GetResponseStream ();

    StreamReader reader = new StreamReader (dataStream);

    string FetchedData = reader.ReadToEnd ();

    reader.Close ();

    dataStream.Close ();

    response.Close ();

    var FetchingDataItems = FetchedData.Split (new char[] { '\n' });

    if (FetchingDataItems != null) {
        var filteredResult = FetchingDataItems.Where (x => x.Contains (referenceNumber));

        return filteredResult;
    } else {
        return null;
    }
}

Now I want to use a component called BTProgressHUD. This is just a fancy spinner. I thought that if I would put BTProgressHUD.show(); to the top of the button action and BTProgressHUD.Dismiss(); to the button it would show when the loading starts and dismiss when its done loading.

This is not the case. It shows very quickly in the new view controller and dismisses again within a second. What am I doing wrong?

Edit for exemple:

public IEnumerable<string> getTrackTraceData (string securityCode, string referenceNumber)
        {


            string url = string.Format ("http://plex.janssen1877.com/app/life/" + securityCode);

            HttpWebRequest HttpRequest = (HttpWebRequest)WebRequest.Create (url);

            string FetchedData = new StreamReader (HttpRequest.GetResponse ().GetResponseStream ()).ReadToEnd ();


            var FetchingDataItems = FetchedData.Split (new char[] { '\n' });

            if (FetchingDataItems != null) {
                var filteredResult = FetchingDataItems.Where (x => x.Contains (referenceNumber));

                return filteredResult;
            } else {
                return null;
            }


        }
Florian Schaal
  • 2,586
  • 3
  • 39
  • 59
  • Are you performing the download in a async fashion? Or, are you running the download in the main thread? If the latter does not fit, maybe the download is very quickly but it's the right behavior. – Lorenzo B Apr 16 '13 at 20:29
  • @flexaddicted I'm using a simple http request for the downloading. I never used async before since I just started programming. See my edit for the download code. – Florian Schaal Apr 16 '13 at 20:35

2 Answers2

3

Florian,

According to .NET documentation and HttpWebRequest GetResponse. How to wait for that response? you need to perform the download (and maybe the parsing) in a async fashion.

The behavior of your actual application is correct. When you perform a sync request in the main thread you freeze the application and hence the UI elements are not updated. The main thread processes execution in a serial fashion.

To avoid this you have two different solutions. On the one hand, you need to move to an async request. On the other hand, you can create a background thread (a different path of execution) with a sync request. I prefer the former. So, for example, after starting the async request, show the indicator. When you have finished (in the callback), dismiss the indicator and perform the segue.

For example, you can follow the following discussion on how to achieve this: How to use HttpWebRequest (.NET) asynchronously?.

To understand how the main thread (and the run loop) works, I suggest to read about The pogo stick of NSRunLoop.

Hope that helps.

Edit

You should use a pattern like the following (source How to use HttpWebRequest (.NET) asynchronously?):

HttpWebRequest webRequest;

void StartWebRequest()
{
    webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}

void FinishWebRequest(IAsyncResult result)
{
    webRequest.EndGetResponse(result);
}
Community
  • 1
  • 1
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
1

It sounds like you're attempting to do all this in the same thread as your UI, which is why your app freezes and waits for processing to finish without showing anything. I would perform this download operation in a backgroundworker of some sort. Then I am not sure in Mono but access the main thread before and after and show and dismiss your loading component.

Bearcat9425
  • 1,580
  • 1
  • 11
  • 12