I am using the following function to get response of a url from web. when i place the response in message box it displays properly.when i put it in text box the programme gets stuck on that statement and doesn't move.why is it happening,as i am feeding the string(response_message) to textbox.
void message_send(int j)
{
int y = 0;
if (CONTACT_NO[j] != "")
{
string Message = "hello";
string url = "some url not mentioned here ";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 30000;
using (WebResponse response = (HttpWebResponse)request.GetResponse())
{
byte[] bytes = ReadFully(response.GetResponseStream());
response_message = System.Text.Encoding.UTF8.GetString(bytes);
// error_logs(str);
MessageBox.Show(response_message);
textBox2.Text = response_message;
}
//textBox3.Text = response_message;
}
else
{
messagebox.show("some message");
}
Since you're multithreading your update to your textbox, you need to be aware that your worker thread can't update the textbox because the textbox wasn't created on the worker thread.
To update the textbox in a thread safe way, I'd recommend the easiest way of invoking:
TextBox2.Invoke((MethodInvoker)(() => { TextBox2.Text = response_message });
I was using my this function in backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) function.which i guess is separate thread.due to which i wasn't able to access textbox1.hence i used the following method to access it.
private void SetText1(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText1);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox2.Text = text;
}
}
Mistake that i was doing i wasn't using the try catch method to check for the exception.which helps me in understanding my issue.
Related
I have written the following code to publish some articles on the Website:
private void btnTransfer_Click(object sender, EventArgs e)
{
//some codes here
counter = 0;
t = new System.Windows.Forms.Timer();
t.Interval = 2000;
t.Tick += t_Tick;
t.Start();
}
int counter;
void t_Tick(object sender, EventArgs e)
{
string cid = cb_destinationSubject.Items[cb_destinationSubject.SelectedIndex].ToString().Split('|')[0];
var wb = new WebClient();
var data = new NameValueCollection();
data["cid"] = cid;
data["title"] =tb_titlePrefix.Text+ postList.ElementAt(counter)[0]+tb_titleSuffix.Text;
data["content"] =tb_textPrefix.Text+ postList.ElementAt(counter)[1]+tb_textSuffix.Text;
if (listBox_images.Items.Count>0)
data["preview"] = listBox_images.Items[new Random().Next(listBox_images.Items.Count)].ToString();
DateTime dt = selector_first_publish.Value.Value;
dt += TimeSpan.FromMinutes((double)(counter * nud_delay.Value));
data["date_time"] = dt.ToString("yyyy-MM-dd HH:mm:ss");
var response = wb.UploadValues(Settings.ApiUrl+"/api/post.php?action=insert","post", data);
var responseString = Encoding.UTF8.GetString(response);
tb_debug.Text += responseString + "\r\n";
if(responseString.Length>5)
lbl_status.Text = responseString;
else
lbl_status.Text =counter.ToString()+" articles has been saved successfully !";
counter++;
if (counter >= postList.Count)
{
counter = 0;
t.Stop();
MessageBox.Show("Done!");
System.Diagnostics.Process.Start(Settings.ApiUrl);
}
}
This Code was working yesterday, but today when I was publishing some new articles (5 articles) I noticed that the first and second article has been published but the third one has been published more than 10 times, then I stopped the program to see what's the problem.
For troubleshooting I created a break line in the following line:
if (counter >= postList.Count)
And realized the third tick never ends, and Visual Studio debug->continue button gets disabled after the pressing it for the second time, and in the break point line visual studio tells me that frmMain.tick is in process.
I figured out that the only difference of the third article is that the string length of that is much more.
But still, I don't get what the problem is, no errors, no exceptions.
******* EDIT *******
I added try catch block like opewix said, but still there is no exceptions,and publishing the third articles goes on until I stop debuging..
void t_Tick(object sender, EventArgs e)
{
try
{
string cid = cb_destinationSubject.Items[cb_destinationSubject.SelectedIndex].ToString().Split('|')[0];
var wb = new WebClient();
var data = new NameValueCollection();
data["cid"] = cid;
data["title"] =tb_titlePrefix.Text+ postList.ElementAt(counter)[0]+tb_titleSuffix.Text;
data["content"] =tb_textPrefix.Text+ postList.ElementAt(counter)[1]+tb_textSuffix.Text;
if (listBox_images.Items.Count>0)
data["preview"] = listBox_images.Items[new Random().Next(listBox_images.Items.Count)].ToString();
DateTime dt = selector_first_publish.Value.Value;
dt += TimeSpan.FromMinutes((double)(counter * nud_delay.Value));
data["date_time"] = dt.ToString("yyyy-MM-dd HH:mm:ss");
//wb.UseDefaultCredentials = true;
//System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
var response = wb.UploadValues(Settings.ApiUrl+"/api/post.php?action=insert","post", data);
var responseString = Encoding.UTF8.GetString(response);
tb_debug.Text += responseString + "\r\n";
if(responseString.Length>5)
lbl_status.Text = responseString;
else
lbl_status.Text =counter.ToString()+" articles has been saved successfully !";
Application.DoEvents();
counter++;
if (counter >= postList.Count)
{
counter = 0;
t.Stop();
MessageBox.Show("انتقال انجام شد");
System.Diagnostics.Process.Start(Settings.ApiUrl);
}
}
catch(Exception ex)
{
throw ex;
}
}
For more information this is the php code I'm using:
/*.. PHP code was unnecessary so is removed ..*/
You have to wrap your Tick handler into try-catch block and then set a breakpoint to catch block, then you'll see an exception. It seems that you're getting exception after submitting request and counter doesn't increment.
Like Enigmativity said, Application.DoEvents(); was the problem !!!
I still don't believe that my program is working, But that's true , Every time I comment the code he said I get the message "Done" and every time I uncomment that code the tick never ends and publishing the third articles goes on...
The reason I used that code was to update the lbl_status Text,Because In some cases in some other programs I've seen Windows Controls doesn't get updated until I use that Application.DoEvents() ..It seems I should study more about this method..Thanks EveryOne,
Im building a program that surf to several websites and do something.
After surfing to like 5 urls successfully, the program hangs after the Application.Run() line.
The program doesn't even enter the Handler function and just stuck. the CPU usage is 0 at this point.
I tried closing the threads in any possible way.
What i'm doing wrong?
I'm doing it like that:
[STAThread]
private static void Main(string[] args)
{
for (int i = 0; i < urls.Count; i++)
{
var th = new Thread(() = >
{
var weBrowser = new WebBrowser();
weBrowser.AllowNavigation = true;
weBrowser.DocumentCompleted += Handler;
weBrowser.Navigate(urls[i]);
Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
th.Join();
}
}
And my Handle function is:
private static void Handler(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser weBrowser = sender as WebBrowser;
var htmlDocument = weBrowser.Document;
/*do something*/
Application.Exit();
Application.ExitThread();
weBrowser.Dispose();
weBrowser.Stop();
Thread.CurrentThread.Abort();
}
My problem is very similar to this one:
Application.Run() leads to application hanging
There is no answer in this question either.
Thanks!
I think you are doing several mistakes:
you are joining inside the for look
you are calling Application.Exit() in each handler call
You should move the joining outside the for loop and do not call Application.Exit.
The following sample seems to work well:
static class Program
{
[STAThread]
static void Main()
{
var urls = new List<string>() {
"http://stackoverflow.com",
"http://stackoverflow.com",
"http://stackoverflow.com",
"http://stackoverflow.com",
"http://stackoverflow.com",
"http://stackoverflow.com",
"http://stackoverflow.com",
"http://stackoverflow.com"};
var threads = new Thread[urls.Count];
for (int i = 0; i < urls.Count; i++)
{
threads[i] = new Thread((url) =>
{
var weBrowser = new WebBrowser();
weBrowser.AllowNavigation = true;
weBrowser.DocumentCompleted += Handler;
weBrowser.Navigate(url as string);
Application.Run();
});
threads[i].SetApartmentState(ApartmentState.STA);
threads[i].Start(urls[i]);
}
foreach (var t in threads)
t.Join();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static void Handler(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser weBrowser = sender as WebBrowser;
var htmlDocument = weBrowser.Document;
/*do something*/
Application.ExitThread();
weBrowser.Dispose();
weBrowser.Stop();
}
}
You may be running into the maximum number of concurrent connections for the WebBrowser. By explicitly setting this to a higher number, you can have additional streams reading through the browser at once.
// Example Usage:
ServicePointManager.DefaultConnectionLimit = 10;
Keep in mind that there is a performance hit by increasing this number above the default (I think it is 4) as you will have much more network traffic that needs processed.
See the MSDN article for ConnectionLimit for more information.
I don't understand what would you like to achieve with Application.Run inside for loop.
Why are you using WebBrowser component? If you are just parsing web page it is better to use
string urlAddress = "http://stackoverflow.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlAddress);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
StreamReader reader= null;
if (response.CharacterSet == null)
reader = new StreamReader(response.GetResponseStream());
else
reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet));
string data = reader.ReadToEnd();
response.Close();
reader.Close();
}
or
using (WebClient client = new WebClient())
{
string html = client.DownloadString("http://stackoverflow.com");
}
For parsing html look at Html Agility Pack or something similar.
If this is console application you don't need to call Application.Run(), otherwise you should consider showing splash screen with progress to give user some feedback.
Usage of urls[i] in your original snippets is wrong. Search C# documentation for closures. You will need to make a local copy before using it.
Furthermore, you should swap weBrowser.Dispose() and weBrowser.Stop(). You can't stop the disposed browser anymore (if Stop is necessary at all).
Finally, don't abort the thread - it will finish itself.
I've seen some great answers here and was wondering if someone could help me out.
Here's my code:
namespace expandGUIWPF
{
public static string getSHA256b64(string filepath)
{
byte[] bytes = SHA256.Create().ComputeHash(File.ReadAllBytes(filepath));
return Convert.ToBase64String(bytes);
}
private void btnRun_Click(object sender, RoutedEventArgs e)
{
{
string folder = txtFolder.Text;
string filelist = folder + "\\FileList.txt";
string[] test = Directory.GetFiles(folder, "*", System.IO.SearchOption.AllDirectories);
File.WriteAllLines(filelist, test);
int length = File.ReadLines(filelist).Count();
pBar1.Minimum = 1;
pBar1.Maximum = length;
File.WriteAllLines(filelist, test);
using (StreamReader sr = new StreamReader(filelist))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string oldfile = line;
string newfile = oldfile + ".expanded";
string oldhash = "";
string newhash = "";
try
{
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\test\test.exe", oldfile + " " + newfile);
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(startInfo);
Thread.Sleep(1000);
if (File.Exists(oldfile))
{
oldhash = getSHA256b64(oldfile);
}
if (File.Exists(newfile))
{
newhash = getSHA256b64(newfile);
File.Delete(oldfile);
File.Move(newfile, oldfile);
}
pBar1.Value = pBar1.Value + 1;
txtLog.AppendText(oldfile + "\r\n Old: " + oldhash + "\r\n New: " + newhash + "\r\n");
if (!(oldhash == newhash))
{
txtLog.AppendText("Successfully expanded file \r\n");
}
else
{
txtLog.AppendText("Unable to expand file \r\n");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
}
}
}
The problem is that my progressbar isn't updating. I know a little C# but I'm a beginner to WPF and can't get my head around setting up a background worker to update my UI. Would someone be able to give me a few pointers please? Currently the app works fine, but the progressbar jumps to 100% finished and all of the text suddenly appears.
Thanks in advance!
Tom
First you'll want your background worker to handle the processes in its DoWork event. Within that event you can call the ProgressChanged event to update the progress bar. Below is an example:
private void btnRun_Click(object sender, RoutedEventArgs e)
{
if(workerThread.IsBusy == false) // Make sure someone doesn't click run multiple times by mistake
{
pBar1.Value = 0;
workerThread.RunWorkerAsync();
}
}
private void workerThread_DoWork(object sender, DoWorkEventArgs e)
{
// Definitions and so forth
pBar1.Minimum = 0;
pBar1.Maximum = length;
int status = 0;
using (StreamReader sr = new StreamReader(filelist))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// Try/Catch work here
status++;
workerThread.ReportProgress(status);
}
}
private void workerThread_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pBar1.Value = e.ProgressPercentage;
}
Just understand that the thread that's running the Form is the same one that will be used to update the form's controls. So if you have 'stuff' to do - like encrypting / decrypting lines from a file - you need to perform those items on another thread with a callback, otherwise the form display wont update until it's done with your stuff to do. You can raise events from inside a worker thread -- and catch them using an event handler on the main (form) thread to update the progress bar.
It seems that your UI thread is being blocked, in windows forms programming you have one message pump and while you main thread (UI) is doing something else it has to wait before it can process messages. You can fix this problem by setting up a background worker to send updates
For more information on UI thread and the message pump see this
http://www.codeproject.com/Articles/10311/What-s-up-with-BeginInvoke
For infomation on the backgroundworker thread see this
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Small Example code
// This event handler is where the time-consuming work is done.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress(i * 10);
}
}
}
I am programming an application for downloading articles from an SQL Database on the internet. I have programmed the Website for managing the articles. Now I'm downloading the article List in gzip Format and then I decompress them to a xml-File. When I'm done I want to insert the articles to the mobile phone. This works great. Now I want to add an progress Bar to see the state of the insertion. I tried with Threading but this doesn't work. I'm posting some pieces of code from my application and also the progressUpdate methods.
private void btn_send_Click(object sender, EventArgs e)
{
label1.Text = "Download started";
string ArticlesURL = "URLTOSITE";
InvokeAsync(ArticlesURL);
}
private void InvokeAsync(string URL)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.AllowWriteStreamBuffering = true;
allDone.Reset();
request.BeginGetRequestStream(new AsyncCallback(ReadArticlesCallback), request);
allDone.WaitOne();
request.BeginGetResponse(new AsyncCallback(ResponseArticlesCallback), request);
}
private static void ReadArticlesCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
//End the operation.
Stream postSream = request.EndGetRequestStream(asynchronousResult);
string postData = "articles=test";
//Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
//Write to the request stream.
postSream.Write(byteArray, 0, postData.Length);
postSream.Close();
allDone.Set();
}
private static void ResponseArticlesCallback(IAsyncResult asynchronousResult)
{
Form1 f = new Form1();
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse resp = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = resp.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
nbrArticles = Convert.ToInt16(responseString);
// Close the stream object.
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse.
resp.Close();
f.truncate_articles();
f.get_articles();
}
private void get_articles()
{
string url = "URLTOSITE";
int startPoint = 0;
DownloadZipFile((object)startPoint, url);
DecompressFile();
getXmlAndInsertInDB();
}
private void getXmlAndInsertInDB()
{
int total = nbrArticles;
int count = total / 100; //How much articles are 1 percent
int i = 0;
String barcode = "";
String name = "";
bool state = false;
XmlTextReader reader = new XmlTextReader("Program Files\\SmartDeviceProject1\\articles.xml");
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element: //The node is an element
while (reader.MoveToNextAttribute()) //Get the attributes like barcode, lastname, firstname, pincode
switch (reader.Name)
{
case "barcode":
barcode = reader.Value.ToString();
state = false;
break;
case "name":
name = reader.Value.ToString();
state = true;
break;
}
break;
}
if (state == true)
{
cmd.CommandText = "INSERT INTO articles(barcode, name) " +
"VALUES('" + barcode + "','" + name + "');";
cmd.ExecuteNonQuery();
state = false;
i++;
if (i == count)
{
Thread t = new Thread(new ThreadStart(this.incrementProgressBar));
t.Start();
//incrementProgressBar();
i = 0;
}
}
}
reader.Close();
}
private void updateProgressBarMethod(int progress)
{
if (progressBar1.InvokeRequired)
{
//It was called from a non UI thread so we create a delegate
//and have the UI Thread call this method again
UpdateProgressBar = new UpdateProgressBarDelegate(updateProgressBarMethod);
this.Invoke(UpdateProgressBar, progress);
}
else
{
//Called from the UI Thread OK to update
//update your progress bar here
progressBar1.Value += progress;
}
}
private void incrementProgressBar()
{
//Call the method to update progress Bar on UI thread
//we do not need a delegate here that will be taken care of
//in the method
updateProgressBarMethod(1);
Application.DoEvents();
}
I think the problem is that I am using Callbacks. I have read that the Callbacks are also starting Threads. So I think the problem is there but I can't solve it.
I've found another very good site for threading with mobile applications: Updating the User Interface from a Worker Thread
Now with the new code, the debugger stops always at the same piece of code without any notification or exception :( Here is my new code:
if (i == count)
{
this.info_percent = "Synchro " + step.ToString() + "%";
this.Invoke(new EventHandler(WorkerUpdate)); //The Debugger stops here!
i = 0;
step++;
Thread.Sleep(700);
}
public void WorkerUpdate(object sender, EventArgs e)
{
this.lbl_percent.Text = this.info_percent;
this.lbl_percent.Update();
this.progressBar1.Value = step;
this.progressBar1.Update();
}
The Debugger stops at: this.Invoke(new EventHandler(WorkerUpdate));
I would suggest using the Background worker class. I had a similar problem and implemented the Background worker and it fixed my problem. Hopefully it will fix yours also
http://www.dotnetperls.com/backgroundworker
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
I found another thread discussing this and thought it would help:
Is there a BackgroundWorker replacement for .NET Compact Framework 3.5?
Your code will always hang at this point:
if (i == count)
{
this.info_percent = "Synchro " + step.ToString() + "%";
this.Invoke(new EventHandler(WorkerUpdate)); //The Debugger stops here!
i = 0;
step++;
Thread.Sleep(700);
}
Make these changes:
public delegate void MethodInvoker(); // this is not defined in CF
if (i == count)
{
this.info_percent = "Synchro " + step.ToString() + "%";
object sender = null; // make this whatever you want/need
EventArgs e = new EventArgs();
if (this.InvokeRequired) {
MethodInvoker mi = delegate { WorkerUpdate(sender, e); } };
this.BeginInvoke(mi);
} else {
WorkerUpdate(sender, e);
}
i = 0;
step++;
// Thread.Sleep(700); Why is this here?
}
This should prevent those obnoxious freezes.
I am using webrequest to fetch some image data. The url may be invaild sometime. In case of invalid URL, begingetresponse is taking time equals to timeout period. Also the control become unresponsive during that period. In other word the async callback is not working asynchronously. Is this expected behaviour?
try
{
// Async requests
WebRequest request = WebRequest.Create(uri);
request.Timeout = RequestTimeOut;
RequestObject requestObject = new RequestObject();
requestObject.Request = request;
request.BeginGetResponse(this.ProcessImage, requestObject);
}
catch (Exception)
{
ShowErrorMessage(uri);
}
private void ProcessImage(IAsyncResult asyncResult)
{
try
{
RequestObject requestObject = (RequestObject)asyncResult.AsyncState;
WebRequest request = requestObject.Request;
WebResponse response = request.EndGetResponse(asyncResult);
Bitmap tile = new Bitmap(response.GetResponseStream());
// do something
}
catch (Exception)
{
ShowErrorMessage();
}
}
looks like this is an issue with .NET. BeginGetResponse blocks until DNS is resolved. In case of wrong URL (like http://somecrap) it tries until it gets timeout. See the following links -
link1 and link2
I just ran into this same situation. While it's not a perfect workaround I decided to use the Ping.SendAsync() to ping the site first. Good part is the async part return immediately. Bad part is the extra step AND not all sites respond to Ping requests.
public void Start(WatchArgs args)
{
var p = new System.Net.NetworkInformation.Ping();
args.State = p;
var po = new System.Net.NetworkInformation.PingOptions(10, true);
p.PingCompleted += new PingCompletedEventHandler(PingResponseReceived);
p.SendAsync(args.Machine.Name, 5 * 1000, Encoding.ASCII.GetBytes("watchdog"), po, args);
}
private void PingResponseReceived(object sender, .PingCompletedEventArgs e)
{
WatchArgs args = e.UserState as WatchArgs;
var p = args.State as System.Net.NetworkInformation.Ping;
p.PingCompleted -= new System.Net.NetworkInformation.PingCompletedEventHandler(HttpSmokeWatcher.PingResponseReceived);
args.State = null;
if (System.Net.NetworkInformation.IPStatus.Success == e.Reply.Status)
{
// ... BeginGetResponse now
}
else
{
/// ... machine not available
}
}
Just code and running for a day but initial result look promising.