I'm building a windows service that grabs information from a website periodically
How can I start looking again when a exception is caught? for example when internet goes down and up later.
Code:
public string cadena(string pagina)
{
try
{
String cadena;
WebRequest myWebRequest = WebRequest.Create(pagina);
myWebrequest = 10000;
WebResponse myWebResponse = myWebRequest.GetResponse();
Stream ReceiveStream = myWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("ISO-8859-1");
StreamReader readStream = new StreamReader(ReceiveStream, encode);
cadena = readStream.ReadToEnd();
readStream.Close();
myWebResponse.Close();
return cadena;
}
catch (WebException error)
{
myTimer.Enabled = true;
return "error";
}
}
public void inicia(object sender, System.Timers.ElapsedEventArgs e)
{
myTimer.Enabled = false;
String strSite = cadena("www.something.com");
//Do something with strSite...
myTimer.Enabled = true;
}
protected override void OnStart(string[] args)
{
myTimer = new System.Timers.Timer();
myTimer.Interval = 1500;
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(inicia);
myTimer.Enabled = true;
}
Here is a very crude example to get you started, this will keep your program from continuing until you get a valid response. There are better ways of doing this, but this is the idea you want. Good luck!
myWebResponse = myWebRequest.GetResponse();
while (myWebResponse.ContentLength == -1) {
//sleep
myWebResponse = myWebRequest.GetResponse();
}
//continue execution
You should probably put in a check to see if the remote site is available, and either poll until it is, or interrupt when the service is available. This way you won't have to recover from a thrown exception.
I think using exceptions should be reserved for things a little more catastrophic to your application.
Related
I have been assigned to take over someones position, however I do not really know C#. There is a server (192.268. something ect) that will post data to a site (unknown site, lets say bleh.com)
This is what the posting code snippet looks like:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
"https://server-ip-here/postlistener?filename=filename.zlib");
req.UseNagleAlgorithm = true;
req.AllowWriteStreamBuffering = true;
req.Method = "POST";
req.Accept = "application/xml";
req.ServicePoint.Expect100Continue = false;
System.Net.ServicePointManager.CheckCertificateRevocationList = false;
req.Proxy = new WebProxy();
filename = "filename.dat";
byte[] postData = File.ReadAllBytes(filename);
Stream stream = req.GetRequestStream();
stream.Write(postData, 0, postData.Length);
stream.Flush();
stream.Close();
req.BeginGetResponse(new AsyncCallback(responseHandler), this);
Which I beleive I get the post request in this form
www.blah.com/upload?filename=file_1234_12389126495129847980.zlib
I am unsure how to listen for post requests and then get the data from them and save them as a file.
Currently I have tried this:
private void Form1_Load(object sender, EventArgs e)
{
listener = new HttpListener();
// listener.Prefixes.Add("http://localhost:8000/");
listener.Prefixes.Add("http://127.0.0.1:8000/");
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
listener.Start();
listenThread1 = new Thread(new ParameterizedThreadStart(startlistener));
listenThread1.Start();
}
private void startlistener(object s)
{
while (true)
{
// blocks until a client has connected to the server
ProcessRequest();
}
}
private void ProcessRequest()
{
var result = listener.BeginGetContext(ListenerCallback, listener);
result.AsyncWaitHandle.WaitOne();
}
private void ListenerCallback(IAsyncResult result)
{
var context = listener.EndGetContext(result);
Thread.Sleep(1000);
var data_text = new StreamReader(
context.Request.InputStream,
context.Request.ContentEncoding).ReadToEnd();
var cleaned_data = System.Web.HttpUtility.UrlDecode(data_text);
context.Response.StatusCode = 200;
context.Response.StatusDescription = "OK";
MessageBox.Show(cleaned_data);
context.Response.Close();
}
Which listens on the local host (Would sub local host for the website once we establish what it will be).
Not sure how to grab the post though, right now I can only listen for it. Ideally I would only like to accept posts from a specific IP address also.
Any ideas how I can go about grabbing the post data (which will be binary) and saving it as a file?
I have the following code to download some files from a FTP Server :
EDIT : I've solved the problem using DotNet, a good FTP WPF Library !
public partial class MainWindow
{
DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
private byte[] downloadedData;
string FTPAddress = "ftp://ftp.cluster007.ovh.net";
double currentBytes;
double oldBytes;
public MainWindow()
{
InitializeComponent();
// DispatcherTimer setup
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
}
public static void DoEvents()
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background,
new Action(delegate { }));
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
currentBytes = Dl_ProgressBar.Value;
Dl_Speed.Content = "Vitesse : " + ((currentBytes - oldBytes) / 1000000).ToString("0.00") + " Mo/s";
oldBytes = Dl_ProgressBar.Value;
// Forcing the CommandManager to raise the RequerySuggested event
CommandManager.InvalidateRequerySuggested();
}
private void Dl_Button_Click(object sender, RoutedEventArgs e)
{
downloadFile();
}
private void downloadFile()
{
downloadedData = new byte[0];
try
{
//Create FTP request
//Note: format is ftp://server.com/file.ext
FtpWebRequest request = FtpWebRequest.Create(FTPAddress + "/" + filename) as FtpWebRequest;
//Get the file size first (for progress bar)
request.Method = WebRequestMethods.Ftp.GetFileSize;
request.Credentials = new NetworkCredential(username, password);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = true; //don't close the connection
int dataLength = (int)request.GetResponse().ContentLength;
Dl_Status.Content = "Téléchargement en cours...";
DoEvents();
//Now get the actual data
request = FtpWebRequest.Create(FTPAddress + "/" + filename) as FtpWebRequest;
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(username, password);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false; //close the connection when done
//Set up progress bar
Dl_ProgressBar.Value = 0;
Dl_ProgressBar.Maximum = dataLength;
//Streams
FtpWebResponse response = request.GetResponse() as FtpWebResponse;
Stream reader = response.GetResponseStream();
//Download to memory
//Note: adjust the streams here to download directly to the hard drive
MemoryStream memStream = new MemoryStream();
byte[] buffer = new byte[1024]; //downloads in chuncks
dispatcherTimer.Start();
while (true)
{
DoEvents(); //prevent application from crashing
int bytesRead = reader.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
//Nothing was read, finished downloading
Dl_ProgressBar.Value = Dl_ProgressBar.Maximum;
Dl_Percent.Content = "Progression : 100%";
DoEvents();
break;
}
else
{
//Write the downloaded data
memStream.Write(buffer, 0, bytesRead);
//Update the progress bar
if (Dl_ProgressBar.Value + bytesRead <= Dl_ProgressBar.Maximum)
{
Dl_ProgressBar.Value += bytesRead;
Dl_Percent.Content = "Progression : " + ((Dl_ProgressBar.Value / 1000000000000000) * dataLength).ToString("0.00") + "%";
DoEvents();
}
}
}
//Convert the downloaded stream to a byte array
downloadedData = memStream.ToArray();
//Clean up
reader.Close();
memStream.Close();
response.Close();
Dl_Status.Content = "Téléchargement terminé";
DoEvents();
}
catch (Exception)
{
Dl_Status.Content = "Erreur de connexion au FTP";
}
}
}
My problem is that when I pass the mouse over the window, the download speed is dropping significantly...
It changes from 3.70Mb/s to 2.20Mb/s.
When I have the mouse out of the window, there's no problem, but when I'm over it, it slows down, particularly when I do some very short movements, the download speed go to 0.20Mb/s.
I've tried to use Threads and Dispatcher but it was the same.
To answer your specific question, WPF's Dispatcher uses a priority queue, and Input level events (like those originating from mouse movement) take priority over Background level events. Your DoEvents() method periodically drains the message queue of all events with Background priority or higher, so when you move the mouse over the window, the queue fills up with input events to process. This means that DoEvents takes longer to return, and more time elapses before you can resume processing the download.
That said, this is a terrible way to accomplish a download; you should never use this kind of DoEvents() hack in WPF; do some research on the async and await features of C# (or, if that is not an option, BackgroundWorker). You will find many examples on StackOverflow of how to perform asynchronous downloads without having to resort to this sort of Dispatcher trickery to keep the UI responsive.
Environemnt : Windows CE / .NET Compact FrameWork 3.5.
I need some guidance in
1) Implementing a Timeout functionality for an Asynchronous Web request.
ThreadPool::RegisterWaitForSingleObject() is not available for .NetCf and I'm bit stuck.
2) How to determine if network itself is not avaialable?
Googling didn't help.
Note : ThreadPool::RegisterWaitForSingleObject is not available for .NET Compact FrameWork.
Here is my Async implementation:
void StartRequest ()
{
try
{
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://192.78.221.11/SomeFunc/excpopulatedept");
RqstState myRequestState = new RqstState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result =
(IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback), myRequestState);
// Release the HttpWebResponse resource.
myRequestState.response.Close();
}
catch (WebException ex)
{
;
}
catch (Exception ex)
{
;
}
}
private void RespCallback(IAsyncResult asynchronousResult)
{
try
{
//State of request is asynchronous.
RqstState myRequestState = (RqstState)asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest = myRequestState.request;
myRequestState.response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(asynchronousResult);
// Read the response into a Stream object.
Stream responseStream = myRequestState.response.GetResponseStream();
myRequestState.streamResponse = responseStream;
// Begin the Reading of the contents of the HTML page and print it to the console.
IAsyncResult asynchronousInputRead = responseStream.BeginRead(myRequestState.BufferRead, 0, 1024, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
catch (WebException e)
{
Console.WriteLine("\nRespCallback Exception raised!");
Console.WriteLine("\nMessage:{0}", e.Message);
Console.WriteLine("\nStatus:{0}", e.Status);
}
}
private void ReadCallBack(IAsyncResult asyncResult)
{
try
{
RqstState myRequestState = (RqstState)asyncResult.AsyncState;
Stream responseStream = myRequestState.streamResponse;
int read = responseStream.EndRead(asyncResult);
// Read the HTML page and then print it to the console.
if (read > 0)
{
myRequestState.requestData.Append(Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read));
IAsyncResult asynchronousResult = responseStream.BeginRead(myRequestState.BufferRead, 0, 1024, new AsyncCallback(ReadCallBack), myRequestState);
return;
}
else
{
//Console.WriteLine("\nThe contents of the Html page are : ");
if (myRequestState.requestData.Length > 1)
{
string stringContent;
stringContent = myRequestState.requestData.ToString();
responseStream.Close();
}
catch (WebException e)
{
}
}
}
}
Thank you for your time.
To continue what Eric J commented on, you have myRequestState.response.Close() just before your catches. That's almost always going to throw an exception because either response will be null, or response won't be opened. This is because you are asynchronously calling BeginGetResponse and the callback you give it will likely not be called by the time the next line (response.close) is called. You'll want to fix that instead of just hiding the exceptions because you don't know why they occur.
In terms of a timeout, because you're dealing with something that doesn't inherently have a configurable timeout, you'll have to set a timer and simply close the connection at the end of the time-out. e.g.
HttpWebRequest myHttpWebRequest; // ADDED
Timer timer; // ADDED
private void StartRequest()
{
myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://192.78.221.11/SomeFunc/excpopulatedept");
RqstState myRequestState = new RqstState();
myRequestState.request = myHttpWebRequest;
timer = new Timer(delegate { if (!completed) myHttpWebRequest.Abort(); }, null, waitTime, Timeout.Infinite); // ADDED
// Start the asynchronous request.
IAsyncResult result =
(IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback), myRequestState);
}
//...
private void ReadCallBack(IAsyncResult asyncResult)
{
try
{
RqstState myRequestState = (RqstState)asyncResult.AsyncState;
Stream responseStream = myRequestState.streamResponse;
int read = responseStream.EndRead(asyncResult);
// Read the HTML page and then print it to the console.
if (read > 0)
{
myRequestState.requestData.Append(Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read));
IAsyncResult asynchronousResult = responseStream.BeginRead(myRequestState.BufferRead, 0, 1024, new AsyncCallback(ReadCallBack), myRequestState);
}
else
{
completed = true; // ADDED
using(timer) // ADDED
{
timer = null;
}
if (myRequestState.requestData.Length > 1)
{
string stringContent;
stringContent = myRequestState.requestData.ToString();
responseStream.Close();
}
}
}
}
I only copy and pasted your code, so it's as likely to compile as what you originally provided, but there should be enough there you get in going in the right direction.
I wrote a simple application in C#. It downloads a log file via ftp, checked whether firefox is running on the PC, changes the log string, uploads the log back to server.
I am running it every 10 seconds using a Timer.
When the service starts, its memory usage is 10Mb and CPU usage <1%. After about two minutes, its memory usage is ~12Mb, but the CPU usage jumps to over 90%!
This is what my app does every 10 seconds:
1) Download log via ftp and store in string log.
2) Go through a list of processes running on the PC, and if there if a firefox.exe process, appropriately change the log string to indicate firefox running.
3) Save the log string to as a txt file, read the file to send id via ftp back to the server.
I doubt saving/reading a couple of lines of text onto hard-drive requires so much CPU power.
Any guesses on what might be going on? Thanks!!
EDIT: Here is my whole class
class Program : System.ServiceProcess.ServiceBase
{
private static System.Timers.Timer timer;
static string myIP = "";
static void start()
{
string strHostName = Dns.GetHostName();
IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
IPAddress[] addr = ipEntry.AddressList;
int i = 0;
foreach (IPAddress address in addr)
{
if (("" + addr[i].AddressFamily).Equals("InterNetwork"))
myIP = "" + addr[i];
i++;
}
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(firefoxChecker); // Everytime timer ticks, timer_Tick will be called
timer.Interval = (1000) * (5);
timer.Enabled = true; // Enable the timer
timer.Start();
}
protected override void OnStart(string[] args)
{
start();
}
public static void Main()
{
System.ServiceProcess.ServiceBase.Run(new Program());
}
static string downloadLog()
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://server/log.txt"));
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential("username", "password");
reqFTP.Proxy = null;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string log = reader.ReadToEnd();
reader.Close();
reader.Dispose();
return log;
}
static void sendLogThroughFTP(string log)
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://server/log.txt"));
reqFTP.Credentials = new NetworkCredential("username", "password");
reqFTP.Proxy = null;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
StreamWriter wr = new StreamWriter(#"C:\logs\temp.txt");
wr.Write(log);
wr.Close();
StreamReader sourceStream = new StreamReader(#"C:\logs\temp.txt");
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
reqFTP.ContentLength = fileContents.Length;
Stream requestStream = reqFTP.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
sourceStream.Dispose();
}
static void firefoxChecker(object sender, EventArgs e)
{
string firefoxOwner = "----------";
TerminalServicesManager manager = new TerminalServicesManager();
ITerminalServer server = null;
string log = downloadLog();
bool diceFirefoxRunning = false;
bool monsterFirefoxRunning = false;
bool careerbuilderFirefoxRunning = false;
try
{
server = manager.GetLocalServer();
server.Open();
foreach (ITerminalServicesSession session in server.GetSessions())
{
if (session.ConnectionState == ConnectionState.Active)
{
firefoxOwner = session.UserAccount.ToString();
string ip = session.ClientIPAddress.ToString();
string user = session.UserAccount.ToString();
System.Collections.Generic.IList<Cassia.ITerminalServicesProcess> list = session.GetProcesses();
foreach (ITerminalServicesProcess process in list)
{
if (Equals(process.ProcessName, "firefox.exe"))
{
// change firefoxOwner string appropriately
log = updateLog(log, user, firefoxOwner);
}
}
}
}
server.Close();
sendLogThroughFTP(log);
}
catch
{
// do nothing
}
}
static string updateLog(string log, string username, string ffOwner)
{
// make some changes to log string
return log;
}
}
}
Thanks for all the inputs!
Disable the timer when you start doing your work and re-enable it when you are done.
You are downloading and uploading via FTP which could take more than the 5 seconds you have set fro your timer. If you disable the timer before you start and re-enable it at the end, you will poll 5 seconds after the last upload completed.
You may also want to consider upping your polling time to something a little more reasonable. Do you really need to poll every 5 seconds to make sure firefox is still running?
Hi guys just wondering if somebody could help me try and correctly thread my application, I am constantly hitting an hurdle after another, I have never been to clued up on threading in applications. I have tryed following this http://www.developerfusion.com/code/4654/asynchronous-httpwebrequest/ tutorial.
basically I'm just trying to stop my request from hanging my application
public class Twitter
{
private const string _username = "****",
_password = "****";
private WebResponse webResp;
public string getTimeLine()
{
Thread thread = new Thread(new ThreadStart(TwitterRequestTimeLine));
thread.IsBackground = true;
thread.Start();
using (Stream responseStream = webResp.GetResponseStream())
{
//
using (StreamReader reader = new StreamReader(responseStream))
{
return reader.ReadToEnd();
}
}
}
private void TwitterRequestTimeLine()
{
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(aUrl);
SetRequestParams(request);
request.Credentials = new NetworkCredential(_username, _password);
//WebResponse tempResp = request.GetResponse();
ThreadState state = new ThreadState();
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(???), ???);
}
private static void SetRequestParams( HttpWebRequest request )
{
request.Timeout = 500000;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "AdverTwitment";
}
}
}
anyone help would be greatly appricated
You really don't need to thread HttpWebRequest.
When you use BeginGetResponse() and EndGetResponse() with HttpWebRequest, it already uses a background thread for you in order to work asynchronously. There is no reason to push this into a background thread.
As for usage: The help for HttpWebRequest.BeginGetResponse demonstrates a complete, asynchronous request.
If this is a WinForms app, the easiest way to keep the GUI responsive while executing the WebRequest is to use a BackgroundWorker component. Drop a BackgroundWorker on your form and call its RunWorkAsync() method. Put the code to execute the WebRequest and read the Response in the DoWork event handler.
Try using an AsyncCallback like Rubens suggested but have the callback call into a separate method to load the data to its destination. If the getTimeline method doesn't return immediately it will cause the application to hang, because the UI Thread is what is running the request itself.
If you use a separate AsyncCallback to be called after the request is done and have it load the data then the method will return immediately and your UI thread can do other things while it waits.
What about this:
private string getTimeLine()
{
string responseValue = "";
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
AutoResetEvent syncRequest = new AutoResetEvent(false);
WebRequest request = WebRequest.Create(aUrl);
request.Method = "POST";
request.BeginGetResponse(getResponseResult =>
{
HttpWebResponse response =
(HttpWebResponse)request.EndGetResponse(getResponseResult);
using (StreamReader reader =
new StreamReader(response.GetResponseStream()))
{
responseValue = reader.ReadToEnd();
}
syncRequest.Set();
}, null);
syncRequest.WaitOne();
return responseValue;
}
EDIT: Ok, I tried to keep a method returning a string, that's why I used AutoResetEvent; If you use a BackgroundWorker, you'll get notified when your data is available:
BackgroundWorker worker = new BackgroundWorker();
string responseValue = "";
worker.RunWorkerCompleted += (sender, e) =>
{
// update interface using responseValue variable
};
worker.DoWork += (sender, e) =>
{
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
WebRequest request = WebRequest.Create(aUrl);
// .. setup
using(StreamReader reader =
new StreamReader(request.GetResponse().GetResponseStream()))
responseValue = reader.ReadToEnd();
};
worker.RunWorkerAsync();