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,
Related
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.
I am making a bulk mail sender which will take mail addresses from DB. All is okay, test mails are sending but the success message is showing only after all the mails are sent. I want a message box or a progress box to count the mails that are passing. Help me to add a message pomp to count the mails have been sending. Here the Code I am using for sending mails, please write me the code for the message box to show the count -
private void btnSendEmail_Click(object sender, EventArgs e){
string subject = txtSubject.Text;
string message = txtMessage.Text;
if (!txtFile.Text.Equals(String.Empty))
{
if (System.IO.Directory.GetFiles(txtFile.Text).Length > 0)
{
foreach (string file in System.IO.Directory.GetFiles(txtFile.Text))
{
}
}
else
{
}
}
var con = "Data Source=Ashiq-pc;Initial Catalog=OfferMails;Integrated Security=True;MultipleActiveResultSets=True";
List<EmailModel> emailList = new List<EmailModel>();
using (SqlConnection myConnection = new SqlConnection(con))
{
string oString = "Select * from tbl_MailAdd where Flag=#Flag";
SqlCommand oCmd = new SqlCommand(oString, myConnection);
oCmd.Parameters.AddWithValue("#Flag", true);
myConnection.Open();
using (SqlDataReader oReader = oCmd.ExecuteReader())
{
while (oReader.Read())
{
EmailModel emailModel = new EmailModel();
emailModel.ID = Convert.ToInt16(oReader["ID"]);
emailModel.EmailAdd = oReader["EmailAdd"].ToString();
emailModel.Flag = Convert.ToBoolean(oReader["Flag"]);
emailList.Add(emailModel);
}
myConnection.Close();
}
}
//return matchingPerson;
foreach (EmailModel email in emailList)
{
try
{
SmtpClient client = new SmtpClient("smtp.gmail.com");
client.Port = 587;
client.EnableSsl = true;
client.Timeout = 100000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("my mail", "my pass");
MailMessage msg = new MailMessage();
msg.To.Add(email.EmailAdd);
msg.From = new MailAddress("my from name");
msg.Subject = subject;
msg.Body = message;
if (!txtFile.Text.Equals(String.Empty))
{
if (System.IO.Directory.GetFiles(txtFile.Text).Length > 0)
{
foreach (string file in System.IO.Directory.GetFiles(txtFile.Text))
{
//Add file in ListBox.
listAttch.Items.Add(file);
//System.Windows.Forms.MessageBox.Show("Files found: " + file, "Message");
Attachment data = new Attachment(file);
msg.Attachments.Add(data);
}
}
else
{
//listBox1.Items.Add(String.Format(“No files Found at location : {0}”, textBox1.Text));
}
}
//Attachment data = new Attachment(textBox_Attachment.Text);
//msg.Attachments.Add(data);
client.Send(msg);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//for (int i = 0; i < emailList.Count; i++)
//{
// MessageBox.Show("i++");
//}
MessageBox.Show("Successfully Sent Message.");
}
First, let me just say that asking for someone to write this code for you is a bit frowned upon here. But I know what you're asking so I'm willing to help out a bit.
Firstly, a message box by itself isn't going to work for this, because a message box ends up stopping the thread where it is until a the DialogResult event is handled. So, for that being said, you will probably want to build another form (I am assuming that you're doing this with Windows Forms here.) to do the progress for you. If you want it to be a counter, then you could do it using a label that is changing its text as each mail is sent.
So, with that being said, however, if you're doing this with a Windows Form, the issue you will run into is the form will never update until after your
foreach loop finishes. This is because of the way that C# handles thread usage.
For what you want to accomplish, you'll need to utilize the BackgroundWorker. This allows you to run cumbersome operations asynchronously.
Here is an example that you could use to get your system working:
//used to be a counter for your progress
int i_counter = 0;
//create a background worker instance
public BackgroundWorker bg_worker = new BackgroundWorker();
public Form1()
{
InitializeComponent();
//set this to true if you want to have an event where you can cancel the background task
bg_worker.WorkerSupportsCancellation = true;
//this is needed to actually show your progress, allows the background worker to report it is working
bg_worker.WorkerReportsProgress = true;
//assigns the "DoWork" and "ProgressChanged" Handlers to the background worker.
bg_worker.DoWork += new DoWorkEventHandler(bg_worker_DoWork);
bg_worker.ProgressChanged += new ProgressChangedEventHandler(bg_worker_ProgressChanged);
}
//Mail method
public void MailerMethod()
{
//all of the things you want to happen for your mailing methods
foreach(//your loop stuff in here)
{
//THIS NEEDS TO HAPPEN TO CAUSE THE COUNTER TO UPDATE
bg_worker.ReportProgress(i_counter);
}
}
//the stuff that you want done in the background
//fires when "RunAsync" is called by BackgroundWorker object.
private void bg_worker_DoWork(object sender, DoWorkEventArgs e)
{
//IN HERE IS WHERE YOU WANT YOUR EMAIL STUFF TO HAPPEN
bg_worker = sender as BackgroundWorker;
MailerMethod();//or just all of your mailing code, it looks nicer like this though
}
//fires when worker reports the progress has changed
//caused by "ReportProgress" method
private void bg_worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
lb_counter.Text = Convert.ToString(i_counter);
}
//this is what will happen when the worker is done.
//you can have it do a alot of things, such as write a report, show a window, etc.
private void bg_worker_RunWorkComplete(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("DONE!", "DING DING!");
Application.Exit();
}
//button click event to start this shindig
private void bt_start_Click(object sender, EventArgs e)
{
//makes sure the background worker isn't already trying to run
if (!bg_worker.IsBusy)
{
//calls the DoWork event
bg_worker.RunWorkerAsync();
bt_start.Visible = false;
}
}
May I direct you here for the official MDSN documentation.
And here for a basic tutorial on how to set up a BackgroundWorker.
Hope this helps, let me know how it goes.
Use a Progress bar with its Position property set to zero, Max property set to the number of emails you are sending and the Step property set to 1, unless you want to step every 10 or so emails then you would use % 10 in your loop to increase the progress. In your loop simply increase the position of the ProgresBar or call Step().
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);
}
}
}
After searching in the Net for about 4 hours I still don't understand Async functions on Windows Phone 7. I tried to run that code but it looks like the event "DownloadStringCompleted" for my webClient is never raised. I tried to wait here for an answer, but it just freeze my app. Anyone could help and explain why it don't work?
internal string HTTPGet()
{
string data = null;
bool exit = false;
WebClient webClient = new WebClient();
webClient.UseDefaultCredentials = true;
webClient.DownloadStringCompleted += (sender, e) =>
{
if (e.Error == null)
{
data = e.Result;
exit = true;
}
};
webClient.DownloadStringAsync(new Uri(site, UriKind.Absolute));
//while (!exit)
// Thread.Sleep(1000);
return data;
}
Ok. Found something!
http://blogs.msdn.com/b/kevinash/archive/2012/02/21/async-ctp-task-based-asynchronous-programming-for-windows-phone.aspx
Yay! :)
Its not a problem with emulator. you want to return the data from your HttpGet() method, but the data is already returned (as null) before the actual response from the webClient occurs. hence I suggest you to make some changes to the code and try.
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri(site, UriKind.Absolute));
and then in the DownloadCompleted event handler(or callback), you manupulate the actual result
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var response= e.Result; // Response obtained from the site
}
The following method is fired when a CD is inserted or ejected.
The problematic code is noted below.
Everything here is based on stepping through the code with breakpoints.
public void CDREventArrived(object sender, EventArrivedEventArgs e)
{
// Get the Event object and display it
PropertyData pd = e.NewEvent.Properties["TargetInstance"];
if (pd != null)
{
ManagementBaseObject mbo = pd.Value as ManagementBaseObject;
if (mbo.Properties["VolumeName"].Value != null)
{
//This line is executed.
textBox1.Text = "test";
//This line is not executed.
//While stepping through the execution,
//I hit F11 on the line above,
//hoping to get to this next line, but it never happens.
//The form pops back up and the step through is complete.
label1.Text = "test";
}
else
{
//Same problem here. Only the first line is hit.
textBox1.Text = "test";
label1.Text = "test";
}
}
}
A related problem is that while it does hit the code to change the text property of textBox1, the text is not actually changed. I can see this on the form and while stepping through breakpoints. So it appears it hits the code, but never actually executes. I'm wondering why it doesn't continue to all the code in the given conditional.
Here is the code which sets up the delegate. This method is called on FormLoad. I stop the listener on form exit.
private void CreateCDRomListener()
{
WqlEventQuery q;
ManagementOperationObserver observer = new
ManagementOperationObserver();
// Bind to local machine
ConnectionOptions opt = new ConnectionOptions();
opt.EnablePrivileges = true; //sets required privilege
ManagementScope scope = new ManagementScope("root\\CIMV2", opt);
try
{
q = new WqlEventQuery();
q.EventClassName = "__InstanceModificationEvent";
q.WithinInterval = new TimeSpan(0, 0, 1);
// DriveType - 5: CDROM
q.Condition = #"TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5";
w = new ManagementEventWatcher(scope, q);
// register async. event handler
w.EventArrived += CDREventArrived;
w.Start();
// Do something usefull,block thread for testing
Console.ReadLine();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
}
}
My first guess is this callback occurs on a thread that is not the UI thread. Try this:
if (InvokeRequired)
{
Invoke(() => textBox1.Text = "test");
}
else
{
textBox1.Text = "test";
}
I think an exception is being triggered at some point.
I would probably put a try/catch in that code to see if something is triggering an exception.
Is there some event handler for the textbox that's being fired when you attempt to change its Text property that is dumping out early?