Ok, I've done some googling, searched these forums, but I couldn't find the answer to my problem. So here it is:
I've got a function in a class that creates a new thread which creates an XMLDocument object and downloads data into it. After it is finished it should somehow pass on that XMLDocument to the main thread (that runs the class, so to speak) so I can get data from it.
So I don't have to access any data while the thread is running, if that makes a difference (and I think it does, from what I've seen so far).
So far the only code I've got working is the code without sharing the XMLDocument when finished, and it is this:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
namespace Lolcats
{
class LolcatsRss
{
private string url = "http://this/is/my/rss/url";
XmlDocument xmlDoc;
Thread webThread;
public LolcatsRss()
{
Thread webThread = new Thread(new ThreadStart(getRss));
webThread.Start();
}
public void getRss() {
XmlDocument _xmlDoc = new XmlDocument();
_xmlDoc.Load(url);
}
}
}
I've tampered with some delegates, but nothing that didn't throw a theading-related exception, so obviously not the right way. Who can enlighten me?
Quick fix (I can't edit my post (?)):
System.Windows.Forms was only there to be able to show a messagebox every now and then, it's not there for any serious purpose and will be removed again, so this is not some kind of control or form, might that not have been clear already.
System.Windows.Drawing is there because there's some image-processing to be done once the XmlDocument is downloaded.
Well Arjay suggested what I was about to explain. Since its a rather complicated solution and hard to explain unless you already know how to work with events I made a little program to show you what hes talking about.
Hope this example helps, i tried to document it the best I could so you would understand whats going on. It works for me, basically it loads an xml document from a thread and populates a ListBox from the nodes it read from the xml document.
The thing is: that's not really what I want to do.
I have 2 threads within the rss-class, one 'main' thread that's running the rss-class, and my other thread that downloads the XML. When the XML-downloading is done, I want the main thread (that's running the rss-class) to have access to the XmlDocument to get some values from it. The XmlDocument does not need to be shared between classes, only between the two threads within that class.
If you already have a thread that the rss-class is running in then why do you need a second thread to download the xml? You're not blocking the UI or anything. You can't just return a object from a thread when the thread is done. You have to fire some event letting the other thread know that the resources are available to use. As soon as the thread that downloads the xml starts, the thread calling it continues. It can't wait for the thread (if it did you wouldn't be using a thread) to return some value.
Monalin is right - why use a thread in the first place. If you have thread A blocking until thread B has loaded the xml document, why not just load the xml document in thread A ?
Code:
The XmlDocument does not need to be shared between classes, only between the two threads within that class.
I think you're confused. A 'thread' is not a member of any class - it is an execution path. As such it can (and does) go everywhere and anywhere, access any data it pleases just as the main thread can.
Threads are not related to classes, it's just in .NET you have a thread class to manage them and enable you to refer to them.
Darwen.
www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.
Monalin is right - why use a thread in the first place. If you have thread A blocking until thread B has loaded the xml document, why not just load the xml document in thread A ?
Code:
The XmlDocument does not need to be shared between classes, only between the two threads within that class.
I think you're confused. A 'thread' is not a member of any class - it is an execution path. As such it can (and does) go everywhere and anywhere, access any data it pleases just as the main thread can.
Threads are not related to classes, it's just in .NET you have a thread class to manage them and enable you to refer to them.
Darwen.
Yeah, some poor choice of words there on my behalf. The 'main' thread runs both the UI and loads the rss-class. Then the rss-class spawns another thread to download the XML. When that is done, the thread that runs both the GUI and the rss-class should be notified and presented somehow with the XmlDocument so it can get some data from the Xml to pass on to the GUI.
I don't want to invoke controls or anything like that, I want to keep it all separated so it's usable in lots of different projects...
Yeah, some poor choice of words there on my behalf. The 'main' thread runs both the UI and loads the rss-class. Then the rss-class spawns another thread to download the XML. When that is done, the thread that runs both the GUI and the rss-class should be notified and presented somehow with the XmlDocument so it can get some data from the Xml to pass on to the GUI.
I don't want to invoke controls or anything like that, I want to keep it all separated so it's usable in lots of different projects...
By modifying my example code i attached slightly you can do just that. I believe my code does what you're looking for. You just need to tweak it a little to work with your system. The same principles apply.
"Then the rss-class spawns another thread to download the XML" - DOES IT
" When that is done, the thread that runs both the GUI and the rss-class should be notified" - DOES IT (via an event)
" and presented somehow with the XmlDocument so it can get some data from the Xml to pass on to the GUI" - DOES IT
If you don't understand the code i attached please ask questions. I think using events and callback functions are the only way you can accomplish what you're trying to do. Heres the slightly modified code, just change Form1.cs to this...
Code:
public XmlDocument xml = new XmlDocument();
public Form1()
{
InitializeComponent();
}
private void populateNames_Click(object sender, EventArgs e)
{
// Create a new instance of the names class
Names myNames = new Names();
// Register the event to fire when we have the xml data
myNames.PopulateNamesComplete += new PopulateNamesCompleteEventHandler(populateNames_Complete);
// Start the new thread
myNames.LoadNames();
}
private void populateNames_Complete(Object sender, PopulateNamesCompleteEventArgs e)
{
// When this thread gets called its still running in the other thread so you can't
// access any of the UI controls on the form unless you do so through a delegate funciton
// if you just wanted to assign a variable you can still do that without invoking
// a delegate method.
xml = e.Xml;
// Show the xml just so you know it completed.
MessageBox.Show(xml.OuterXml);
}
Ah, pass it as part of the event arguments, hadn't noticed that yet, sorry. That indeed seems like it will work exactly like I want it to! I'll change it so that the rss-class is listening to the event itself and then it should work exactly like I want. Thanks!
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.