Search code examples
c#observablecollectioniasyncresultasynccallback

Why is list Empty?


I am able to access the list (ListData) value from within its class, but if I try to reference the list from outside of the class, it shows it as an empty list.

I add objects to ListData in the getVideoList method.

I added this piece of code and it works now (Polling method) , Is this ineffiencient ?

 IAsyncResult result = request.BeginGetResponse(new AsyncCallback(getVideoList), state);
            while (result.IsCompleted == false)
            {
               Thread.Sleep(1000);
             }

Public class otherclass{
    static void main(string [] args){
      RestProcess process = new RestProcess(videoListURI);
      process.initilaizeRest();

      foreach (VideoSeriesElement ele in process.ListData)
      {
        Console.WriteLine(ele.id);
        Console.WriteLine(ele.title);
        Console.WriteLine(ele.href);
        Console.WriteLine(ele.image);
      }

      Console.ReadLine();
  }

}

public class RestProcess
{
    /// <summary>
    /// Default constructor
    /// </summary>
    /// 
    readonly string blankimage = "http://images1.test.com/properties/NoThumbnail_HD.jpg";
    public RestProcess(string uri)
    {
        URI = uri;
        ListData = new ObservableCollection<VideoSeriesElement>();
    } 
    public ObservableCollection<VideoSeriesElement> ListData{get;set;}


    public void initilaizeRest()
    {
        WebRequest request = HttpWebRequest.Create(URI);
        request.Method = "GET";

        // RequestState is a custom class to pass info to the callback
        RequestState state = new RequestState(request, URI);
        IAsyncResult result = request.BeginGetResponse(new AsyncCallback(getVideoList), state);
    }

    public string URI{get;set;}

    /// <summary>
    /// getVideoList
    /// </summary>
    /// <param name="result"></param>
    public void getVideoList(IAsyncResult result)
    {
        RequestState state = (RequestState)result.AsyncState;
        WebRequest request = (WebRequest)state.Request;
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);

        try
        {
            TextReader textreader = new StreamReader(response.GetResponseStream()); 
            XDocument doc = XDocument.Load(textreader);


            foreach(XElement videoSeriesEle in doc.Descendants("video-series"))
            {
                var videseriesEle = new VideoSeriesElement();    
                videseriesEle.id = videoSeriesEle.Attribute("id").Value;
                videseriesEle.href = videoSeriesEle.Attribute("href").Value;
                videseriesEle.title = videoSeriesEle.Element("title").Value;

                if (!videoSeriesEle.Element("images").IsEmpty && videoSeriesEle.Element("images").Elements("image") != null)
                {
                    var imagelist = videoSeriesEle.Element("images").Elements("image").ToList();
                    foreach (var ele in imagelist)
                    {
                        if (ele.Attribute("styleid").Value.Equals("5"))
                        {
                            if (videoSeriesEle.Element("images").Element("image").Attribute("href").Value != null)
                            {
                                videseriesEle.image = videoSeriesEle.Element("images").Element("image").Attribute("href").Value;
                            }

                        }
                    }

                }
                else { videseriesEle.image = blankimage; }


                //add object to list 
                ListData.Add(videseriesEle);

            }

            //Close streams 
            textreader.Close();
            response.Close();
        }
        catch (XmlException e)
        {
            Console.WriteLine(e);
        }

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="state"></param>
    /// <param name="timedOut"></param>
    private static void ScanTimeoutCallback(object state, bool timedOut)
    {
        if (timedOut)
        {
            RequestState reqState = (RequestState)state;
            if (reqState != null)
                reqState.Request.Abort();
            Console.WriteLine("aborted- timeout");
        }
    }
}

Solution

  • The RestProcess.initilaizeRest() method requests the data via an IAsyncResult, meaning the call to get the data is asynchronous. In your otherClass class, you attempt to process and loop through the ListData element immediately after calling initilaizeRest() and there is a very good chance that the data is not loaded yet.

    To fix this, you should have a callback/event-handler in the otherClass that listens for when the data is populated.