Threads: Raising an event in the original thread

  • Thread starter Thread starter James Dunkerley
  • Start date Start date
J

James Dunkerley

Hi,

I am trying to create a class which downloads a web page in the background
and then raises an event in the original thread in which it was created.
This class is going to be the basis of a set of different applications and I
want to hide the threading from the other layers. Any suggestions as to how
to do this?

Thanks
James
 
That is basically what I am doing at the moment. However the event by
the Downloader class is in the thread t.

For most usages this isn't a problem as most elements of .Net as
"thread-safe". However Win32 forms are not thread safe. One way round
this is to invoke the method you want to call on the form. I am trying
to avoid this as we want the threading to handled inside the
Downloader class and the end user to be unaware that it has changed
thread.

Any ideas?

Thanks
James

This is current source code we are using:

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Reflection;
using System.Threading;

namespace Web
{
public class ResultsArgs : EventArgs
{
private string strResult;

public ResultsArgs(string strDownload) : base()
{
strResult = strDownload;
}

public string strWebPage
{
get
{
return strResult;
}
}
}

public delegate void RequestComplete(object sender, ResultsArgs e);

public class HTTPConnect
{
#region Class Variables
private string strProxyURL;

public event RequestComplete OnRequestComplete;

private Thread _MasterThread;
private string _strURL;
private string _strPostText;
#endregion
#region Constructor
public HTTPConnect()
{
this.LoadObject();

_MasterThread = Thread.CurrentThread;
if (strProxyURL == "") strProxyURL =
"http://proxy.jdunkerley.co.uk:80";
}
#endregion
#region Request Functions
public string WebRequest(string strURL)
{
string strResponse="";

WebRequest wrqRequest = System.Net.WebRequest.Create(strURL);

WebProxy isa = new WebProxy(strProxyURL);
isa.BypassProxyOnLocal = true;
wrqRequest.Proxy = isa;

WebResponse wrsResponse = wrqRequest.GetResponse();

Stream srmStream = wrsResponse.GetResponseStream();
StreamReader srdResponse = new StreamReader(srmStream);
if(srdResponse!= null)
{
strResponse = srdResponse.ReadToEnd();
srdResponse.Close();
}
srdResponse.Close();

return strResponse;
}

public string WebRequest(string strURL, string strPostText)
{
if (strPostText == "")
{
return WebRequest(strURL);
}
else
{
string strResponse="";

WebRequest wrqRequest = System.Net.WebRequest.Create(strURL);
HttpWebRequest hwrRequest = (HttpWebRequest)wrqRequest;

WebProxy isa = new WebProxy(strProxyURL);
isa.BypassProxyOnLocal = true;
hwrRequest.Proxy=isa;

hwrRequest.Method = "POST";
hwrRequest.ContentType = "application/x-www-form-urlencoded";
hwrRequest.UserAgent = "Mozilla/4.0";
hwrRequest.Accept = "text/html";

hwrRequest.ContentLength = strPostText.Length;
StreamWriter swrPostText = new
StreamWriter(hwrRequest.GetRequestStream(), Encoding.ASCII);
if(swrPostText != null)
{
swrPostText.Write(strPostText);
swrPostText.Close();
}

HttpWebResponse hwrResponse =
(HttpWebResponse)hwrRequest.GetResponse();
StreamReader srdResponse = new
StreamReader(hwrResponse.GetResponseStream(), Encoding.ASCII);
if(srdResponse!= null)
{
strResponse = srdResponse.ReadToEnd();
srdResponse.Close();
}
srdResponse.Close();

return strResponse;
}
}

public void WebRequestBackground(string strURL)
{
this.WebRequestBackground(strURL, "");
}

public void WebRequestBackground(string strURL, string strPostText)
{
this._strURL = strURL;
this._strPostText = strPostText;

ThreadStart tstEntryPoint = new
ThreadStart(WebRequestBackgroundEntryPoint);
Thread trdBackgoundRequest = new Thread(tstEntryPoint);
trdBackgoundRequest.Name = "JWMP.Web.HTTPConnect Background
Request";
trdBackgoundRequest.IsBackground = true;
trdBackgoundRequest.Start();
}

private void WebRequestBackgroundEntryPoint()
{
string strResponse = "";

strResponse = WebRequest(_strURL,_strPostText);

RaiseRequestComplete(this, strResponse);
}

public static void RaiseRequestComplete(HTTPConnect caller,
string strResponse)
{
if (caller.OnRequestComplete != null)
caller.OnRequestComplete(caller, new
JWMP.Web.ResultsArgs(strResponse));
}

public string WebRequest(string strURL, string strPostText, bool
blnRunInBackground)
{
if (blnRunInBackground)
{
WebRequestBackground(strURL, strPostText);
return "";
}
else
{
return WebRequest(strURL, strPostText);
}
}
#endregion
}
}
 
Hi James,
We can swtich therads (execute the event handler in the caller thread
context) only if the caller thread is a UI thread (has a message loop).
Switching threads is based on the windows messaging system. If the caller
thread is not a UI thred you can use a some sync objects, which the worker
thread can signal. In this case, though, the caller thread has to do some
work to check this objects periodically and fire appropriate events in its
context. Which in turn means that the caller thread cannot be unaware of the
existance of the worker thread.
Anyway, if you come up with something I would be really curious to see the
idea. I believe it will benefit to all in the group if you post the idea.

B\rgds
100
 
Hi James,
Probably the best I've come up with is not to actually hand-off the method
to the original thread using any signalling but simply to execute the method
in the threadpool by calling BeginInvoke on a delegate to the method/event.
Doesnt quite solve the problem but ensures that the thread throwing the
event doesnt get tied up.

Hope this helps,
Kieran
 
Back
Top