Why is list Empty? - c#

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");
}
}
}

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.

You can expose IAsyncResult result as a property from the request.BeginGetResponse call in RestProcess and block in otherClass until the IAsyncResult.IsCompleted property is true, or use the WaitHandle exposed by it, but is there a reason that you're using the async BeginGetResponse call rather than the synchronous GetResponse call?

Related

XML Deserialization C#

I am trying to deserialize an XML file into an object in the Program file of my Windows Forms application as below:
List<UserAccessGroup> AccessGroups = new List<UserAccessGroup>();
AccessGroups = SerializerHelper.DeSerializeObject<List<UserAccessGroup>>(#"C:\Users\Michael"
+ #"\Google Drive\FDM Dev Course Content\Workspace\SystemAdmin\SystemAdmin\"
+ #"XML Data Store\UserAccessGroups.xml");
UserAccessGroup SystemAdmin_App = new UserAccessGroup();
foreach (UserAccessGroup group in AccessGroups)
{
if (group.Name.Equals("Admin Operators"))
{
SystemAdmin_App = group;
}
}
When I run this code, I am getting an unhandled exception in my foreach loop, stating that Access Groups is null.
However, when I copy and paste this snippet of code into a blank console application, it runs fine and when I check AccessGroups with a break point, it has 4 members, as expected.
Can anyone please tell me why deserialization is not working in my program file?
Also, here is my XML file:
<?xml version="1.0"?>
<ArrayOfUserAccessGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<UserAccessGroup>
<Name>Admin Operators</Name>
<Access_Group>
<int>999</int>
</Access_Group>
</UserAccessGroup>
<UserAccessGroup>
<Name>Shareholders</Name>
<Access_Group />
</UserAccessGroup>
<UserAccessGroup>
<Name>Brokers</Name>
<Access_Group />
</UserAccessGroup>
<UserAccessGroup>
<Name>StockExMgrs</Name>
<Access_Group />
</UserAccessGroup>
</ArrayOfUserAccessGroup>
EDIT: forgot to include the SerializerHelper class that I am using for serialization/deserialization, please see below:
public static class SerializerHelper
{
/// <summary>
/// Serializes an object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="serializableObject"></param>
/// <param name="fileName"></param>
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(
"SerializerHelper.cs");
public static void SerializeObject<T>(string filepath, T serializableObject)
{
if (serializableObject == null) { return; }
try
{
XmlDocument xmlDocument = new XmlDocument();
XmlSerializer serializer = new XmlSerializer(serializableObject.GetType());
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, serializableObject);
stream.Position = 0;
xmlDocument.Load(stream);
xmlDocument.Save(filepath);
stream.Close();
}
}
catch (Exception ex)
{
//Log exception here
logger.Error("Error Serializing: " + ex.Message);
}
}
/// <summary>
/// Deserializes an xml file into an object list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileName"></param>
/// <returns></returns>
public static T DeSerializeObject<T>(string filepath)
{
T objectOut = default(T);
if (!System.IO.File.Exists(filepath)) return objectOut;
try
{
string attributeXml = string.Empty;
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(filepath);
string xmlString = xmlDocument.OuterXml;
using (StringReader read = new StringReader(xmlString))
{
Type outType = typeof(T);
XmlSerializer serializer = new XmlSerializer(outType);
using (XmlReader reader = new XmlTextReader(read))
{
objectOut = (T)serializer.Deserialize(reader);
reader.Close();
}
read.Close();
}
}
catch (Exception ex)
{
//Log exception here
logger.Error("Error Deserializing: " + ex.Message);
}
return objectOut;
}
}
EDIT: UserAccessGroup class below:
[Serializable]
public class UserAccessGroup : IUserAccessGroup
{
private String name;
private List<int> AccessGroup = new List<int>();
public String Name
{
get { return name; }
set { name = value; }
}
public List<int> Access_Group
{
get { return AccessGroup; }
set { AccessGroup = value; }
}
public UserAccessGroup()
{
}
public UserAccessGroup(String name)
{
this.name = name;
}
public List<int> getUserIDs()
{
return AccessGroup;
}
public void removeUser(int userID)
{
AccessGroup.Remove(userID);
return;
}
public void addUser(int userID)
{
AccessGroup.Add(userID);
return;
}
}
The main problem can be summarized as:
T objectOut = default(T);
if (!System.IO.File.Exists(filepath)) return objectOut;
try
{
// ...
}
catch (Exception ex)
{
//Log exception here
logger.Error("Error Deserializing: " + ex.Message);
}
return objectOut;
(note that default(T) for T=List<UserAccessGroup> is null)
So: for AccessGroups to be null, one of 2 things is happening:
the file does not exist (so the code is exiting near the top)
an exception is being thrown
Check each of these. If the first: add it. If the second: read the .Message, and the .InnerException.Message etc (XmlSerializer is very big on inner-exceptions)
XmlSerializer will not return null for the root object of a list / array, so: it is one of those two things.
Put a breakpoint on the not-exists return, and in the catch, and you should find what is happening. Alternatively, look at where-ever logger writes. Maybe also add something that writes to logger when the file doesn't exist.

C# Modifying multiple Dictionary Values throws error

I'm using HTML Agility Pack to download some pages, I'm also storing cookie info and login info from a form. The issue I'm having is that I'm doing a GET operation to get the cookie info and form details so on the next step it can login using a username and password, I'm then trying to set the value of the username and password input fields so that I can then post to a login page. The input fields are being stored in a Dictionary<string,string>. I'm able to change one of the dictionary values, but after that I get the error:
"Object reference not set to an instance of an object.".
If I try to change password and then username the username throws the error and vice-versa. This is the code im using:
class Main
{
private void testLogin()
{
BrowserSession b = new BrowserSession();
b.Get("login.html");
b.FormElements["email_address"] = #"email";
b.FormElements["password"] = "password";
string response = b.Post("index.php?main_page=login");
}
}
}
public class BrowserSession
{
private bool _isPost;
private HtmlDocument _htmlDoc;
/// <summary>
/// System.Net.CookieCollection. Provides a collection container for instances of Cookie class
/// </summary>
public CookieCollection Cookies { get; set; }
/// <summary>
/// Provide a key-value-pair collection of form elements
/// </summary>
public FormElementCollection FormElements { get; set; }
/// <summary>
/// Makes a HTTP GET request to the given URL
/// </summary>
public string Get(string url)
{
_isPost = false;
CreateWebRequestObject().Load(url);
return _htmlDoc.DocumentNode.InnerHtml;
}
/// <summary>
/// Makes a HTTP POST request to the given URL
/// </summary>
public string Post(string url)
{
_isPost = true;
CreateWebRequestObject().Load(url, "POST");
return _htmlDoc.DocumentNode.InnerHtml;
}
/// <summary>
/// Creates the HtmlWeb object and initializes all event handlers.
/// </summary>
private HtmlWeb CreateWebRequestObject()
{
HtmlWeb web = new HtmlWeb();
web.UseCookies = true;
web.PreRequest = new HtmlWeb.PreRequestHandler(OnPreRequest);
web.PostResponse = new HtmlWeb.PostResponseHandler(OnAfterResponse);
web.PreHandleDocument = new HtmlWeb.PreHandleDocumentHandler(OnPreHandleDocument);
return web;
}
/// <summary>
/// Event handler for HtmlWeb.PreRequestHandler. Occurs before an HTTP request is executed.
/// </summary>
protected bool OnPreRequest(HttpWebRequest request)
{
AddCookiesTo(request); // Add cookies that were saved from previous requests
if (_isPost) AddPostDataTo(request); // We only need to add post data on a POST request
return true;
}
/// <summary>
/// Event handler for HtmlWeb.PostResponseHandler. Occurs after a HTTP response is received
/// </summary>
protected void OnAfterResponse(HttpWebRequest request, HttpWebResponse response)
{
SaveCookiesFrom(response); // Save cookies for subsequent requests
}
/// <summary>
/// Event handler for HtmlWeb.PreHandleDocumentHandler. Occurs before a HTML document is handled
/// </summary>
protected void OnPreHandleDocument(HtmlDocument document)
{
SaveHtmlDocument(document);
}
/// <summary>
/// Assembles the Post data and attaches to the request object
/// </summary>
private void AddPostDataTo(HttpWebRequest request)
{
string payload = FormElements.AssemblePostPayload();
byte[] buff = Encoding.UTF8.GetBytes(payload.ToCharArray());
request.ContentLength = buff.Length;
request.ContentType = "application/x-www-form-urlencoded";
System.IO.Stream reqStream = request.GetRequestStream();
reqStream.Write(buff, 0, buff.Length);
}
/// <summary>
/// Add cookies to the request object
/// </summary>
private void AddCookiesTo(HttpWebRequest request)
{
if (Cookies != null && Cookies.Count > 0)
{
request.CookieContainer.Add(Cookies);
}
}
/// <summary>
/// Saves cookies from the response object to the local CookieCollection object
/// </summary>
private void SaveCookiesFrom(HttpWebResponse response)
{
if (response.Cookies.Count > 0)
{
if (Cookies == null) Cookies = new CookieCollection();
Cookies.Add(response.Cookies);
}
}
/// <summary>
/// Saves the form elements collection by parsing the HTML document
/// </summary>
private void SaveHtmlDocument(HtmlDocument document)
{
_htmlDoc = document;
FormElements = new FormElementCollection(_htmlDoc);
}
}
public class FormElementCollection : Dictionary<string, string>
{
/// <summary>
/// Constructor. Parses the HtmlDocument to get all form input elements.
/// </summary>
public FormElementCollection(HtmlDocument htmlDoc)
{
var inputs = htmlDoc.DocumentNode.SelectSingleNode("//div[#id = 'loginDefault']").Descendants("input");
foreach (var element in inputs)
{
string name = element.GetAttributeValue("name", "undefined");
string value = element.GetAttributeValue("value", "");
if (!name.Equals("undefined")) { Add(name, value); }
}
}
/// <summary>
/// Assembles all form elements and values to POST. Also html encodes the values.
/// </summary>
public string AssemblePostPayload()
{
StringBuilder sb = new StringBuilder();
foreach (var element in this)
{
string value = HttpUtility.UrlEncode(element.Value);
sb.Append("&" + element.Key + "=" + value);
}
return sb.ToString().Substring(1);
}
}
Any help would be much appreciated.
While debugging put a break point after calling the b constractor.
You ll find the FormElements property is Null.
You need to inialize it in BrowserSession constractor.

Calling a method in C#

I have problem to call a method in a WCFService. I downladed the file below for a project and I want to call a method in SampleHttpResquestAndResponse class in my WCFService (Also, I tried to do it in a main method and i couldn't succeed it either). However I can't do it, i can't find the method when I type it. How to call those methods in SampleHttpResquestAndResponse class?
using System;
using System.IO;
using System.Net;
using System.Text;
using System.IO.Compression;
using System.Xml.Serialization;
namespace Sample
{
public class SampleHttpResquestAndResponse
{
/// <summary>
/// Adonis servisi ile iletişim kurmayı sağlar.
/// </summary>
/// <typeparam name="T">T</typeparam>
/// <param name="prm_ServiceName">string</param> SearchHotels // BasketHotels // ConfirmHotels
/// <param name="prm_Criteria">object</param>
/// <param name="prm_Url">string</param> "http://xmltest.adonis.com/AdonisServices"
/// <returns>T</returns>
public static T AdonisRequestResponseMethod<T>(string prm_ServiceName, object prm_Criteria, string prm_Url)
{
#region Variables
HttpWebRequest HttpWebRequest;
T ReturnValue;
#endregion
try
{
#region Xml Serializer
var XmlString = SampleHttpResquestAndResponse.ConvertTypeToXml<object>(prm_Criteria).ToString();
#endregion
#region Http Web Request
HttpWebRequest = (HttpWebRequest)WebRequest.Create(string.Format("{0}/{1}?prm_CurrentData={2}", prm_Url, prm_ServiceName, XmlString));
HttpWebRequest.ContentType = "text/xml;charset=\"utf-8\"";
HttpWebRequest.Method = "POST";
HttpWebRequest.Timeout = 80000000;
#endregion
#region Http Web Response
StreamWriter StreamWriterPost = new StreamWriter(HttpWebRequest.GetRequestStream());
StreamWriterPost.Write(XmlString);
StreamWriterPost.Close();
HttpWebResponse HttpWebResponse = (HttpWebResponse)HttpWebRequest.GetResponse();
StreamReader StreamReaderResponse = new StreamReader(HttpWebResponse.GetResponseStream(), Encoding.UTF8);
string StringResponse = string.Empty;
if (HttpWebResponse.ContentEncoding.ToLower().Contains("gzip"))
{
using (GZipStream decompress = new GZipStream(HttpWebResponse.GetResponseStream(), CompressionMode.Decompress))
{
StreamReader reader = new StreamReader(decompress);
StringResponse = reader.ReadToEnd();
}
}
else
{
StreamReader reader = new StreamReader(HttpWebResponse.GetResponseStream(), Encoding.UTF8);
StringResponse = reader.ReadToEnd();
}
#endregion
#region Return Value Type Process (DESERIALIZE)
ReturnValue = SampleHttpResquestAndResponse.ConvertXmlToType<T>(StringResponse.ToString()).Data;
#endregion
#region Return Value
return ReturnValue;
#endregion
}
catch (Exception ex)
{
#region Return Value
return ReturnValue = SampleHttpResquestAndResponse.ConvertXmlToType<T>(ex.Message).Data;
#endregion
}
}
public static ResultDTO<T> ConvertXmlToType<T>(string prm_Xml)
{
#region Variables
T ReturnValue;
#endregion
try
{
#region Replace String Value
prm_Xml = prm_Xml.Replace("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
, "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
prm_Xml = prm_Xml.Replace("<", "<").Replace(">", ">").Replace(""", "\"");
#endregion
#region Deserialize
using (MemoryStream MemoryStream = new MemoryStream())
{
using (StreamWriter StreamWriter = new StreamWriter(MemoryStream))
{
StreamWriter.Write(prm_Xml);
StreamWriter.Flush();
MemoryStream.Position = 0;
XmlSerializer XmlSerializer = new XmlSerializer(typeof(T));
using (StreamReader StreamReader = new StreamReader(MemoryStream))
{
StreamReader.ReadLine();
#region Result Value (SET)
ReturnValue = (T)XmlSerializer.Deserialize(StreamReader);
#endregion
}
}
}
#endregion
#region Return Value
return new ResultDTO<T>
{
Data = ReturnValue,
Success = true
};
#endregion
}
catch (Exception ex)
{
#region Return Value
return new ResultDTO<T>
{
Success = false,
Message = string.Format("Error Type : {0} Code : {1} Method Name : {2} Error Mesage : {3}", "Undetermined", "1000", "ConvertXmlToType", ex.Message),
};
#endregion
}
}
public static string ConvertTypeToXml<T>(T prm_Criteria)
{
#region Variables
XmlSerializer XmlSerializer;
StringWriter StringWriter = new StringWriter();
#endregion
try
{
#region Xml Serializer
XmlSerializer = new XmlSerializer(prm_Criteria.GetType());
XmlSerializer.Serialize(StringWriter, prm_Criteria);
var XmlString = StringWriter.ToString();
#endregion
#region Request Replace
return XmlString = XmlString.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
#endregion
}
catch (Exception ex)
{
throw ex;
}
finally
{
GC.SuppressFinalize(StringWriter);
}
}
}
public class ResultDTO
{
#region Properties
/// <summary>
/// İslem durumu.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// İşlem mesajı.
/// </summary>
public string Message { get; set; }
#endregion
}
public class ResultDTO<T> : ResultDTO
{
#region Fields
/// <summary>
/// Generic data tipi.
/// </summary>
private T data = Activator.CreateInstance<T>();
#endregion
#region Properties
/// <summary>
/// Generic data tipi
/// </summary>
public T Data
{
get
{
if (data == null)
return data = default(T);
return data;
}
set { data = value; }
}
#endregion
}
}
PS: I know it is a little bit silly question, but i couldn't figure it. If it is needed, the below is how i try to call any method in this class in a simple way
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.IO;
using System.Net;
using System.Text;
using System.IO.Compression;
using System.Xml.Serialization;
using Sample;
namespace Adonis
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "AdonisService" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select AdonisService.svc or AdonisService.svc.cs at the Solution Explorer and start debugging.
public class AdonisService : IAdonisService
{
ResultDTO res = new ResultDTO();
SampleHttpResquestAndResponse samp = new SampleHttpResquestAndResponse();
public string results()
{
string a1 = "";
object c = new object();
c = 434;
string b = "";
string a = "";
a= samp.AdonisRequestResponseMethod(a, c, b);
}
}
}
AdonisRequestResponseMethod is static, and as such would be called like this:
SampleHttpResquestAndResponse.AdonisRequestResponseMethod(a, b, c);
However, it is also a generic method, so you will have to supply the type you require:
SampleHttpResquestAndResponse.AdonisRequestResponseMethod<string>(a, b, c);
I see 2 things wrong here:
The method is both a generic method.
Since it's a generic method, you must provide a type for it:
SampleHttpResquestAndResponse samp = new SampleHttpResquestAndResponse ();
samp.AdonisRequestResponseMethod<SomeType>(a, b, c);
However, that's not the complete answer,
It's a static method, which means that you can't reference the method from an instance of the class, rather you must reference it from the class type
SampleHttpResquestAndResponse.AdonisRequestResponseMethod<SomeType>(a, b, c);
Oh, and one more thing... SampleHttpResquestAndResponse has an extra 's' in the 'Request' portion of the name. That might give you headaches later. Hope this helps!

Json Geocode address parsing in C#

I want to get address of the location
Iam using google geocode to get address by passing lat and long.
static readonly string RequestUrl = "http://maps.google.com/maps/api/geocode/json?";
/// <summary>
/// Gets the raw object.
/// </summary>
/// <returns></returns>
protected JsonGeoData GetJsonObject() {
StringBuilder url = new StringBuilder( GeoRequest.RequestUrl);
if (this.Location != null) {
url.AppendFormat("latlng={0}", this.Location.ToString());
}
else {
url.AppendFormat("address={0}", HttpUtility.UrlEncode(this.Address));
}
url.AppendFormat("&sensor={0}", this.IsSensor.ToString().ToLower());
if (!string.IsNullOrEmpty(this.Language))
url.AppendFormat("&language={0}", HttpUtility.UrlEncode(this.Language));
if(!string.IsNullOrEmpty(this.Region))
url.AppendFormat("&region={0}", HttpUtility.UrlEncode(this.Region));
WebRequest request = WebRequest.Create(url.ToString());
using (WebResponse response = request.GetResponse()) {
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Deserialize<JsonGeoData>(reader.ReadToEnd());
}
}
}
/// <summary>
/// Gets the response.
/// </summary>
/// <returns></returns>
public GeoResponse GetResponse() {
return new GeoResponse(this.GetJsonObject());
}
/// <summary cref="A">
/// fetching location from web
/// </summary>
/// <typeparam name="T"></typeparam>
private string getloc(double plat, double plng)
{
try
{
GeoRequest objreq = new GeoRequest(plat, plng);
GeoResponse objres = objreq.GetResponse();
if (objres.Results.Count > 0)
{ return objres.Results[0].FormattedAddress; }
else
{ return "Unknown"; }
}
catch (FormatException) { return "Unknown"; }
catch (Exception)
{ return "Unknown"; }
}
iam trying to get json data from geocode and parse using serializer,
But iam getting error 'sublocality_level_2 is not a valid value for GeoAddressType.'

How to pass a data from new thread?

I have a class:
class ShowComboBoxUpdater
{
private ComboBox _showComboBox;
private String _searchString;
private RequestState _endState;
public event EventHandler ResultUpdated;
public string[] getShowList()
{
if (_endState.serverQueryResult != null)
return _endState.serverQueryResult;
return new string[] { "" };
}
public ShowComboBoxUpdater(ComboBox combo, Image refreshImage)
{
_showComboBox = combo;
_refreshImage = refreshImage;
_endState = new RequestState();
}
public void RequestUpdatingComboSource()
{
_searchString = _showComboBox.Text;
Thread t = new Thread(new ThreadStart(MakeServerConnectionThread));
t.IsBackground = true;
t.Start();
}
private void MakeServerConnectionThread()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://services.tvrage.com/myfeeds/search.php?show=" + _searchString);
_endState.request = request;
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(RequestingThread), _endState);
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(ScanTimeoutCallback), _endState, (30 * 1000), true);
}
private void RequestingThread(IAsyncResult result)
{
RequestState state = (RequestState)result.AsyncState;
WebRequest request = (WebRequest)state.request;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
Stream bodyStream = response.GetResponseStream();
StreamReader r = new StreamReader(bodyStream);
string xmlResponse = r.ReadToEnd().Trim();
using (StringReader XMLStream = new StringReader(xmlResponse))
{
XPathNavigator feed = new XPathDocument(XMLStream).CreateNavigator();
XPathNodeIterator nodesNavigator = (XPathNodeIterator)feed.Evaluate("descendant::show/name/text()");
int titlesCount = nodesNavigator.Count;
string[] titles = new string[titlesCount];
foreach (XPathNavigator n in nodesNavigator)
{
titles[--titlesCount] = n.Value;
}
state.serverQueryResult = titles;
if (this.ResultUpdated != null) this.ResultUpdated(this, new EventArgs());
}
}
private static void ScanTimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
RequestState reqState = (RequestState)state;
if (reqState != null)
reqState.request.Abort();
}
}
}
In my main thread I create ShowComboBoxUpdater and connect event ResultUpdate to other event. Then I am calling RequestUpdatingComboSource() method. I have my event activated but, how can I get the resulting serverQueryResult ? I know it's there but everything that I try results in exception that what I want to get is "owned by other thread".
How to pass value ?
public class MyArgs : EventArgs
{
//Declare any specific type here
public string ResultToPass { get; private set; }
public MyArgs()
{
}
}
if (this.ResultUpdated != null) this.ResultUpdated(this, new MyArgs(){ResultToPass="Your actual result"} );
How to update result ?
Capture SynchronizationContext of the UI ( main thread) in order to instruct whenever you want the value to be updated back in the UI. Send/Post method on the captured SynchronizationContext reference in order to push the message into UI thread.
public partial class MainWindow : Window
{
SynchronizationContext UISyncContext;
public MainWindow()
{
InitializeComponent();
}
public StartProcessing()
{
//Let say this method is been called from UI thread. i.e on a button click
//capture the current synchronization context
UISyncContext=TaskScheduler.FromCurrentSynchronizationContext;
}
public UpdateResultInUI()
{
//Let's say this is is the method which user triggers at
//some point in time ( with the assumption that we have Myresult in hand)
if(UISyncContext!=null)
UISyncContext.Send(new SendOrPostCallback(delegate{ PutItInUI }),null);
//Use Send method - to send your request synchronously
//Use Post method- to send your request asynchronously
}
void PutItInUI()
{
//this method help you to put your result in UI/controls
}

Categories