I have the following code which seems to throw a "Invalid cross-thread access." and I can't seem to figure out why. I'm loading a remote xml file from a URL, however, when parsing that XML I always receive this error. Any suggestions?
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
string xml = streamReader.ReadToEnd();
using (XmlReader reader = XmlReader.Create(new StringReader(xml)))
{
reader.ReadToFollowing("channel");
reader.MoveToFirstAttribute();
reader.ReadToFollowing("title");
output.AppendLine("Title: " + reader.ReadElementContentAsString());
reader.ReadToFollowing("description");
output.AppendLine("Desc: " + reader.ReadElementContentAsString());
textBox1.Text = output.ToString(); //Invalid cross-thread access.
}
}
The XML I'm trying to parse looks like the following, I'm just trying to parse bits and pieces as I continue to learn how to use c# to parse different types of XML:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"xmlns:dc="http://purl.org /dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0 /modules/slash/">
<channel>
<title>Server & Site News</title>
<description>A place for the Admin and Moderators to post the latest news on both the server and site.</description>
<pubDate>Fri, 18 May 2012 22:45:08 +0000</pubDate>
<lastBuildDate>Fri, 18 May 2012 22:45:08 +0000</lastBuildDate>
<generator>Forums</generator>
<link>http://removedurl.com/forums/server-site-news.23/</link>
<atom:link rel="self" type="application/rss+xml" href="http://removedurl.com/forums/server-site-news.23/index.rss"/>
<item>
<title>Example Title</title>
<pubDate>Mon, 14 May 2012 17:39:45 +0000</pubDate>
<link>http://removedurl.com/threads/back-fully-working.11013/</link>
<guid>http://removedurl.com/threadsback-fully-working.11013/</guid>
<author>Admin</author>
<dc:creator>Admin</dc:creator>
<slash:comments>14</slash:comments>
</item>
</channel>
textBox1.Text = output.ToString(); //Invalid cross-thread access.
you get that because you are calling UI thread while you are doing operations on IO thread. Try separating those operations or call invoke on the UI thread.
try changing your code to something like this.
Dispatcher.BeginInvoke( () => { //your ui update code } );
To add a bit more detail from Mayank:
Dispatcher.BeginInvoke( () => {
textBox1.Text = output.ToString()
} );
You have to marshal the call to UI objects back to the UI thread. Nothing can modify UI elements on any other thread than the main one.
Related
I am using merger api in my product, my code looks like the below
ExtractOptions extractOptions = new ExtractOptions(new int[] { i, i });
using (Merger merger = new Merger(mStream))
{
string fullFileName = filePathOut + fileVersionId.ToString() + “_” + i.ToString() +
fileExtension.ToLower();
merger.ExtractPages(extractOptions);
merger.Save(fullFileName);
}
while I extract pages from file with more then 4 pages, I am getting the following error
At most 4 elements (for any collection) can be viewed in evaluation mode.
I am using
Groupdocs.merger 20.4
Groupdocs.viewer 19.6
Groupdocs.Parser 19.5
and my license is valid upto 20.8 version
below is template of my license file
<License>
<Data>
<LicensedTo>My company name.</LicensedTo>
<EmailTo>Email</EmailTo>
<LicenseType>Developer OEM</LicenseType>
<LicenseNote>Limited to 1 developer, unlimited physical locations</LicenseNote>
<OrderID></OrderID>
<UserID></UserID>
<OEM>This is a redistributable license</OEM>
<Products>
<Product>GroupDocs.Total for .NET</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SerialNumber></SerialNumber>
<SubscriptionExpiry>20200905</SubscriptionExpiry>
<LicenseVersion>3.0</LicenseVersion>
<LicenseInstructions></LicenseInstructions>
</Data>
<Signature></Signature>
</License>
I don’t understand why the above error is apearing, can anyone help me on this?
Am I missing something?
I am writing a method in c# that gets xml from web service with a lot of data that I do not need. I managed to select only tags that I need with this command:
var exchangeRateDataSet = xmlNew.Descendants("ExchangeRateDataSet");
Now I need to convert it to string so I can deserialize it and convert it to object of my class.
But, there is a problem. When i try to do this:
var toRead = exchangeRateDataSet.ToString();
I get this as a string, which of course isn't valid: System.Xml.Linq.XContainer+d__39
This is a piece of xml that I have:
``
<?xml version="1.0"?>
<ExchangeRateDataSet xmlns="">
<ExchangeRate xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" msdata:rowOrder="0" diffgr:id="ExchangeRate1">
<ExchangeRateListNumber>111</ExchangeRateListNumber>
<Date>14.06.2019</Date>
<CreateDate>14.06.2019</CreateDate>
<DateTo>31.12.4172</DateTo>
<ExchangeRateListTypeID>1</ExchangeRateListTypeID>
<CurrencyGroupID>2</CurrencyGroupID>
<CurrencyCode>978</CurrencyCode>
<CurrencyCodeNumChar>978</CurrencyCodeNumChar>
<CurrencyCodeAlfaChar>EUR</CurrencyCodeAlfaChar>
<CurrencyNameSerCyrl>Евро</CurrencyNameSerCyrl>
<CurrencyNameSerLat>Evro</CurrencyNameSerLat>
<CurrencyNameEng>Euro</CurrencyNameEng>
<CountryNameSerCyrl>ЕМУ</CountryNameSerCyrl>
<CountryNameSerLat>EMU</CountryNameSerLat>
<CountryNameEng>EMU</CountryNameEng>
<Unit>1</Unit>
<BuyingRate>117.6265</BuyingRate>
<MiddleRate>0.0000</MiddleRate>
<SellingRate>118.3343</SellingRate>
<FixingRate>0.000000</FixingRate>
</ExchangeRate>
<ExchangeRate xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" msdata:rowOrder="1" diffgr:id="ExchangeRate2">
<ExchangeRateListNumber>111</ExchangeRateListNumber>
<Date>14.06.2019</Date>
<CreateDate>14.06.2019</CreateDate>
<DateTo>31.12.4172</DateTo>
<ExchangeRateListTypeID>1</ExchangeRateListTypeID>
<CurrencyGroupID>3</CurrencyGroupID>
<CurrencyCode>36</CurrencyCode>
<CurrencyCodeNumChar>036</CurrencyCodeNumChar>
<CurrencyCodeAlfaChar>AUD</CurrencyCodeAlfaChar>
<CurrencyNameSerCyrl>Аустралијски долар</CurrencyNameSerCyrl>
<CurrencyNameSerLat>Australijski dolar</CurrencyNameSerLat>
<CurrencyNameEng>Australian Dollar</CurrencyNameEng>
<CountryNameSerCyrl>Аустралија</CountryNameSerCyrl>
<CountryNameSerLat>Australija</CountryNameSerLat>
<CountryNameEng>Australia</CountryNameEng>
<Unit>1</Unit>
<BuyingRate>71.9868</BuyingRate>
<MiddleRate>0.0000</MiddleRate>
<SellingRate>72.4200</SellingRate>
<FixingRate>0.000000</FixingRate>
</ExchangeRate>
``
To summarize, my question is how to convert this xml to object?
Any help would be appreciated. Thanks.
using CsQuery;
namespace CSQuery
{
class Program
{
static void Main(string[] args)
{
var dom = CQ.Create(/*I am not sure what goes here*/);
//Not sure if this is the correct setup as well
CQ mf = dom["MANUFACTURER"];
CQ md = dom["MODEL"];
Console.WriteLine(mf);
Console.WriteLine(md);
Console.ReadKey();
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
--------------------------------------------------------
PARTS:
Title: Computer Parts
<ITEM>Motherboard</ITEM>
<MANUFACTURER>ASUS</MANUFACTURER>
<MODEL>P3B-F</MODEL>
<COST> 123.00</COST>
<ITEM>Video Card</ITEM>
<MANUFACTURER>ATI</MANUFACTURER>
<MODEL>All-in-Wonder Pro</MODEL>
<COST>160.00</COST>
<ITEM> Monitor </ITEM>
<MANUFACTURER>LG Electronics</MANUFACTURER>
<MODEL> 995E</MODEL>
<COST> 290.00</COST>
</PART></PARTS>
Above is my code I have written so far I am trying to extract the MANUFACTURER and MODEL from the sample given xml code. When I compile I get an error message saying source can not be found and I think it may be a problem with my setup and I am unclear on what exactly is suppose to go into my CQ.Create() as a parameter(I tried putting in the exact parts.xml file but that didn't help).
----- UPDATED -----
I have a question, simple for the more experts in c# (I am a Java dissident) and I will apreciate your help to do a good thing here using the right technique and technologies.
What I need
Load a XML file from a URL.
After this I need navigate between the information sets getting the data and put it into some variables.
This will be a .NET C# executable program , stand alone that other program in COBOL will run and recuperate the data.
The exemple XML is:
<?xml version="1.0" encoding="utf-8"?>
<movie>
<title>
Fast Five
</title>
<year>
2011
</year>
<description>
Dominic Toretto and his crew of street racers plan a massive heist ...
</description>
<director>
<director_1>Justin Lin</director_1>
<director_2>Vovó Mafalda</director_2>
</director>
</movie>
Accessible in, localhost:8080\movie.xml, for example.
I have a code to load a XML:
namespace main
{
public class XMLLoader
{
public static void getXMLContent()
{
String title = null;
String year = null;
String description = null;
String director1 = null;
String director2 = null;
String director3 = null;
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://localhost:8081/xml/movies.xml");
title = (xmlDoc.GetElementsByTagName("title")[0]).InnerText.Trim();
year = (xmlDoc.GetElementsByTagName("year")[0]).InnerText.Trim();
description = (xmlDoc.GetElementsByTagName("description")[0]).InnerText.Trim();
director1 = (xmlDoc.GetElementsByTagName("director_1")[0]).InnerText.Trim();
director2 = (xmlDoc.GetElementsByTagName("director_2")[0]).InnerText.Trim();
director3 = (xmlDoc.GetElementsByTagName("director_3")[0]).InnerText.Trim();
Console.WriteLine("Movie......: " + title);
Console.WriteLine("Year.......: " + year);
Console.WriteLine("Description: " + description);
Console.WriteLine("Director1..: " + director1);
Console.WriteLine("Director2..: " + director2);
Console.WriteLine("Director3..: " + director3);
}
catch (Exception e)
{
Console.WriteLine(" Error to load URL");
Console.WriteLine(" Message: " + e.Message);
}
}
static void Main(string[] args)
{
getXMLContent();
Console.ReadKey();
}
}
}
But this smells bad for me.
There is a more efficient and beautiful way to do it?
And how to load a XML from a URL in a console C# program?
Thanks for all help and attention.
XmlDocument can read from a URI:
XmlDocument doc = new XmlDocument();
doc.Load("http://localhost:8080/movie.xml");
var movie = doc.SelectSingleNode("/movies/movie");
There are a few different ways of reading XML from C#. For simple, small structures (and especially remote ones), I find XmlDocument to be the shortest method.
If you are using a recent version of the .NET Framework (3.5 or later I think) you can use the XDocument class which has Load and Parse methods on it. Once you have your XDocument class you can use Linq to XML to build an anonymous type to hold your data, something like:-
const string xmlData = #"<?xml version=""1.0"" encoding=""utf-8""?><movie><title>Fast Five</title><year>2011</year><description>Dominic Toretto and his crew of street racers plan a massive heist to buy their freedom while in the sights of a powerful Brazilian drug lord and a dangerous federal agent.</description><director>Justin Lin</director></movie>";
var xdoc = XDocument.Parse(xmlData);
var movie = from docRoot in xdoc.Descendants("movie")
let titleElement = docRoot.Element("title") where titleElement != null
let yearElement = docRoot.Element("year") where yearElement != null
let descriptionElement = docRoot.Element("description") where descriptionElement != null
select new
{
Title = titleElement.Value,
Year = yearElement.Value,
Description = descriptionElement.Value
};
You can use LinQ to XML to get the data from an XML structure. Here's an article on this. Basically if this is your XML:
<movies>
<movie>
<title>
Fast Five
</title>
<year>
2011
</year>
<description>
Dominic Toretto and his crew of street racers plan a massive heist to buy their freedom while in the sights of a powerful Brazilian drug lord and a dangerous federal agent.
</description>
<director>
Justin Lin
</director>
</movie>
<movies>
Your code looks like this:
XElement xelement = XElement.Load("PATH_TO_XML");
IEnumerable<XElement> movies = xelement.Elements();
foreach (var movie in movies)
{
var title = employee.Element("title").Value);
//and so on...
}
The description is bit on the longer side please bear with me. I would like to process and validate a huge XML file and log the node which triggered the validation error and continue with processing the next node. A simplified version of the XML file is shown below.
What I would like to perform is on encountering any validation error processing node 'A' or its children (both XMLException and XmlSchemaValidationException) I would like to stop processing current node log the error and XML for node 'A' and move on to the next node 'A'.
<Root>
<A id="A1">
<B Name="B1">
<C>
<D Name="ID" >
<E>Test Text 1</E>
</D>
<D Name="text" >
<E>Test Text 1</E>
</D>
</C>
</B>
</A>
<A id="A2">
<B Name="B2">
<C>
<D Name="id" >
<E>Test Text 3</E>
</D>
<D Name="tab1_id" >
<E>Test Text 3</E>
</D>
<D Name="text" >
<E>Test Text 3</E>
</D>
</C>
</B>
</Root>
I am currently able to recover from the XmlSchemaValidationException by using a ValidationEventHandler with XMLReader which throws a Exception that I handle in the XML Processing code. However for some cases XMLException is being triggered which leads to termination of the process.
The following snippets of the code illustrate the current structure I am using; it is messy and code improvement suggestions are also welcome.
// Setting up the XMLReader
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.IgnoreWhitespace = true;
settings.CloseInput = true;
settings.IgnoreComments = true;
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(null, "schema.xsd");
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
XmlReader reader = XmlReader.Create("Sample.xml", settings);
// Processing XML
while (reader.Read())
if (reader.NodeType == XmlNodeType.Element)
if (reader.Name.Equals("A"))
processA(reader.ReadSubtree());
reader.Close();
// Process Node A
private static void processA(XmlReader A){
try{
// Perform some book-keeping
// Process Node B by calling processB(A.ReadSubTree())
}
catch (InvalidOperationException ex){
}
catch (XmlException xmlEx){
}
catch (ImportException impEx){
}
finally{ if (A != null) A.Close(); }
}
// All the lower level process node functions propagate the exception to caller.
private static void processB(XmlReader B){
try{
// Book-keeping and call processC
}
catch (Exception ex){
throw ex;
}
finally{ if (B != null) B.Close();}
}
// Validation event handler
private static void ValidationCallBack(object sender, ValidationEventArgs e){
String msg = "Validation Error: " + e.Message +" at line " + e.Exception.LineNumber+
" position number "+e.Exception.LinePosition;
throw new ImportException(msg);
}
When a XMLSchemaValidationException is encountered the finally block will invoke close() and the original XMLReader is being positioned on the EndElement of the subtree and hence the finally block in processA will lead to processing of the next node A.
However when a XMlException is encountered invoking the close method is not positioning the original reader on the EndElement node of the subtree and an InvalidOperationException is being throw.
I tried to use methods like skip, ReadToXYZ() methods but these are invariably leading to XMLExcpetion of InvalidOperationException when invoked on any node that triggered an exception.
The following is a excerpt from MSDN regarding the ReadSubTree method.
When the new XmlReader has been
closed, the original XmlReader will be
positioned on the EndElement node of
the sub-tree. Thus, if you called the
ReadSubtree method on the start tag of
the book element, after the sub-tree
has been read and the new XmlReader
has been closed, the original
XmlReader is positioned on the end tag
of the book element.
Note: I cannot use .Net 3.5 for this, however .Net 3.5 suggestions are welcome.
See this question:
XML Parser Validation Report
You need to distinguish between well-formed xml (it follows the rules required to be real xml) and valid xml (follows additional rules given by a specific xml schema). From the spec:
Once a fatal error is detected, however, the processor must not continue normal processing (i.e., it must not continue to pass character data and information about the document's logical structure to the application in the normal way).
For better or worse, the xml tools included with Visual Studio need to follow that spec very closely, and therefore will not continue processing if there is a well-formedness error. The link I provided might give you some alternatives.
I have done this almost like you have, except for the exception eating and questionable use XmlReader.Close():
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.IgnoreWhitespace = true;
settings.CloseInput = true;
settings.IgnoreComments = true;
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(null, "schema.xsd");
settings.ValidationEventHandler += ValidationCallBack;
using (XmlReader reader = XmlReader.Create("Sample.xml", settings))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element &&
reader.Name.Equals("A"))
{
using (
XmlReader subtree = reader.ReadSubtree())
{
try {
processA(subtree);
}
catch (ImportException ex) { // log it at least }
catch (XmlException ex) {// log this too }
// I would not catch InvalidOperationException - too general
}
}
}
}
private static void processA(XmlReader A)
{
using (XmlReader subtree = A.ReadSubtree())
{
processB(subtree);
}
}
// All the lower level process node functions propagate the exception to caller.
private static void processB(XmlReader B)
{
}
You don't want to eat the exceptions, except for those from processA. Let the caller of processA decide wihch exceptions to ignore - processA should not be aware of that. Same with the using blocks - put them on the outside, rather than the inside.