locked
WinPhone 7: Cross Thread Access Error RRS feed

  • Question

  • I have a Win7 phone application that is using HttpRequest/HttpReponse object to pull data from a web site.  The code to do the async calls work and i get the data I expect back.  The call to ProcessReturnData form the GetResponseCallback function also works.  The issue is when I pass the data back to the MainViewModel.cs.  It catches the exception correctly and reads the return datat, but when it tries to add records to the the data behind the form (thus updating the field that are bound to the form objects, I get an 'Invalid - cross thread access' error.  I understand why this is happening, but i cannot figure out how to 'close' the async threads and return control over to the original thread (UI thread).  I have read that I could use the page.Dispatcher (which I could pass to the GetSiteList method), but then I would be tightly binding ServiceProvider classes to the Win7 phone UI.  This would defeat the purpose of these classes since I plan on refactoring these classes to separate project so they can be used to build a similar application for iPhone/Android using MonoTouch and MonoDroid.  Any help on how to take care of this and return control back to the original thread before or after calling the OnDataLoaded event would be helpful.

    I have the following code in a base class (ServiceProviderBase.cs)

    #region Events Handlers
        public void GetRequestCallback(IAsyncResult asynchronousResult)
        {
          RequestData requestData = (RequestData)asynchronousResult.AsyncState;
          HttpWebRequest request = requestData.request;
    
          try
          {
            Stream postStream = request.EndGetRequestStream(asynchronousResult);
            postStream.Write(Encoding.UTF8.GetBytes(requestData.postData), 0, requestData.postData.Length);
            postStream.Close();
    
            request.BeginGetResponse(new AsyncCallback(GetResponseCallback), requestData);
          }
          catch (Exception ex)
          {
            HandleAsyncErrors("There was a problem sending the request to the the provider.", ex);
          }
        }
    
        public void GetResponseCallback(IAsyncResult asynchronousResult)
        {       
          HttpWebRequest request = (HttpWebRequest)((RequestData)asynchronousResult.AsyncState).request;
          HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
    
          Stream streamResponse = null;
          StreamReader streamReader = null;
          string returnData = String.Empty;
    
          try
          {
            streamResponse = response.GetResponseStream();
            streamReader = new StreamReader(streamResponse);
    
            returnData = streamReader.ReadToEnd();
            returnData = returnData.Replace((Char)10, (Char)0).Replace((Char)13, (Char)0).Replace("\0","");
            ProcessReturnData(returnData);
          }
          catch (Exception ex)
          {
            HandleAsyncErrors("There was a problem retrieving the data from the provider.", ex);
          }
          finally
          {
            if(streamResponse != null) streamResponse.Close();
            if (streamReader != null) streamReader.Close();
          }
        }
        #endregion
    
        #region Public Methods
        public void MakeWebRequest(string serviceURL, string userName, string password, string postData)
        {
          RequestData requestData = new RequestData();
          HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceURL);   
          
          if (!String.IsNullOrEmpty(userName) && !String.IsNullOrEmpty(password))
          {
            request.Credentials = new NetworkCredential(userName, password);
          }
          request.ContentType = "application/xml";
          request.Accept = "application/xml";
          request.Method = "POST";
    
          requestData.request = request;
          requestData.postData = postData;
    
          request.BeginGetRequestStream(new AsyncCallback(GetResponseCallback), requestData);
          } 
        #endregion
    

     

    And the following code in the class that inherits from it (ServiceProvider)

    public override void GetSitesList()
    {
      try
      {
       MakeWebRequest("https://somesite.com", "userName", "password", "");
      }
      catch (Exception ex)
      {
       OnProviderError(this, new EventArgs());
      }
    }
    
    public override void ProcessReturnData(string returnData)
    {
      try
      {
       SiteInfoList = SiteInfo.ParseAndLoadData(returnData);
       OnDataLoaded(this, new EventArgs());
      }
      catch (Exception ex)
      {
       OnProviderError(this, new EventArgs());
      }
    }
    

    Thanks,

     

    • Moved by Figo Fei Monday, November 1, 2010 7:30 AM (From:Visual C# General)
    Friday, October 29, 2010 1:31 AM

Answers