I have some code that uses a custom popupNotifier that subscribes to a click event like so:
popupNotifier1.Click += new EventHandler(PopUpClicked);
That means when someone clicks open the popup it launches a url string. Assume _url is global for the time being.
I do this in PopUpClicked:
public void PopUpClicked(object sender, EventArgs e)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(_url);
proc.StartInfo = startInfo;
proc.Start();
}
The url, _url contains a string like:
http://mysite/mypage.aspx?MyID=100
This works all fine..it opens the page but I noticed it will open up multiple tabs of the same page.
I cant understand why?
edit
Just to add more code I call this from a timer event that hits every minute, but notice the if condition, it only subscribes to the event if there is data:
private void timer1_Tick(object sender, EventArgs e)
{
SqlDataReader sr;
string ticketInfo = String.Empty;
string url = String.Empty;
bool hasData = false;
using (SqlConnection sc = new SqlConnection(_connString))
{
using (SqlCommand scmd = new SqlCommand("select_poll"))
{
scmd.Connection = sc;
scmd.CommandType = CommandType.StoredProcedure;
scmd.Parameters.Add("LoginID", SqlDbType.BigInt).Value = _userLoginID;
scmd.Parameters.Add("FacilityID", SqlDbType.BigInt).Value = _userFacilityID;
sc.Open();
sr = scmd.ExecuteReader(CommandBehavior.CloseConnection);
if (sr != null)
{
while (sr.Read())
{
hasData = true;
ticketInfo += sr["TicketID"].ToString() + " - " + sr["Ticket"].ToString() + Environment.NewLine;
_url = "http://mysite/mypage.aspx?ID=" + sr["TicketID"].ToString();
}
}
}
}
if (hasData)
{
popupNotifier1.TitleColor = System.Drawing.Color.Green;
popupNotifier1.ContentText = ticketInfo;
popupNotifier1.Scroll = true;
popupNotifier1.TitlePadding = new System.Windows.Forms.Padding(2);
popupNotifier1.ContentPadding = new System.Windows.Forms.Padding(2);
popupNotifier1.Image = Properties.Resources.medical;
popupNotifier1.ImagePadding = new System.Windows.Forms.Padding(10);
popupNotifier1.Click += new EventHandler(PopUpClicked);
popupNotifier1.Popup();
}
}
public void PopUpClicked(object sender, EventArgs e)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(_url);
proc.StartInfo = startInfo;
proc.Start();
}
You're subscribing to the event multiple times. In this particular case, you're subscribing to the event any time a particular condition is met when your timer fires. It would appear that this happens more than once.
You almost certainly want to attach the event handler outside of the tick event, probably when the form is first loaded.
popupNotifier1.Click += new EventHandler(PopUpClicked);
the above lines subscribes to the event multiple times, so when first time, when PopUp is fires, it opens one tab, next time 2 tab, then next time three tab n so on
add handler only once, the best way will be, just before u enable the timer in your code
Like
popupNotifier1.Click += new EventHandler(PopUpClicked);
timer1.Enabled = true;
Fixed Code
private void timer1_Tick(object sender, EventArgs e)
{
SqlDataReader sr;
string ticketInfo = String.Empty;
string url = String.Empty;
bool hasData = false;
using (SqlConnection sc = new SqlConnection(_connString))
{
using (SqlCommand scmd = new SqlCommand("select_poll"))
{
scmd.Connection = sc;
scmd.CommandType = CommandType.StoredProcedure;
scmd.Parameters.Add("LoginID", SqlDbType.BigInt).Value = _userLoginID;
scmd.Parameters.Add("FacilityID", SqlDbType.BigInt).Value = _userFacilityID;
sc.Open();
sr = scmd.ExecuteReader(CommandBehavior.CloseConnection);
if (sr != null)
{
while (sr.Read())
{
hasData = true;
ticketInfo += sr["TicketID"].ToString() + " - " + sr["Ticket"].ToString() + Environment.NewLine;
_url = "http://mysite/mypage.aspx?ID=" + sr["TicketID"].ToString();
}
}
}
}
if (hasData)
{
popupNotifier1.TitleColor = System.Drawing.Color.Green;
popupNotifier1.ContentText = ticketInfo;
popupNotifier1.Scroll = true;
popupNotifier1.TitlePadding = new System.Windows.Forms.Padding(2);
popupNotifier1.ContentPadding = new System.Windows.Forms.Padding(2);
popupNotifier1.Image = Properties.Resources.medical;
popupNotifier1.ImagePadding = new System.Windows.Forms.Padding(10);
popupNotifier1.Popup();
}
}
public void PopUpClicked(object sender, EventArgs e)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(_url);
proc.StartInfo = startInfo;
proc.Start();
}
Related
I have spent some time designing my first project using C#, it is a Windows form project with 8 buttons on the side. pressing one of the buttons will open another form within the parent form as a window. On clicking the button the new form loads up about 27 objects mostly Labels, Textboxes, Comboboxes and a few DateTimePickers. For some reason it you can see it drawing the boxes and it looks slow. I have an SQL db included with my project which is tiny and contains only 2 rows of data. It is very dishearting to spend all that time working on it only to see it run like a ZX Spectrum. I am using Microsoft Visual Studio 2019 and is fully updated. I have no errors, no warnings thank god but the performance is horrible. One of the comboBoxes when selected will make visible 3 more textBoxes and even making those visible is really slow. Is there something I am doing wrong or is there a way to have it working faster please?
This is the code of my childForm which opens from the main parentForm, sorry is is a bit long but it is all of it.
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace AvianManager.Forms
{
public partial class formMyBirds : Form
{
SqlConnection connection = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Dion\Documents\AvianManager.mdf;Integrated Security=True;Connect Timeout=30");
public formMyBirds()
{
InitializeComponent();
}
private void formMyBirds_Load(object sender, EventArgs e)
{
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void pictureBox1_Click(object sender, EventArgs e)
{
var form = Application.OpenForms["formMyBirdsHelper"]; // Lookup form and check if already open
if (form == null)
{
formMyBirdsHelper MyBirdsHelper = new formMyBirdsHelper(); // Instantiate a FormMyBirdsHelp object.
MyBirdsHelper.Show(); // Show FormMyBirdsHelp and
}
}
private void comboBoxLegBandType_SelectedIndexChanged(object sender, EventArgs e)
{
string selected = this.comboBoxLegBandType.GetItemText(this.comboBoxLegBandType.SelectedItem);
if (selected != "None" || selected == null)
{
textBoxLegBandID.Visible = true;
labelLegBandId.Visible = true;
textBoxLegBandSize.Visible = true;
labelLegBandSize.Visible = true;
}
else
{
textBoxLegBandID.Visible = false;
labelLegBandId.Visible = false;
textBoxLegBandSize.Visible = false;
labelLegBandSize.Visible = false;
}
}
private void comboBoxPrevOwner_SelectedIndexChanged(object sender, EventArgs e)
{
string selected = this.comboBoxPrevOwner.GetItemText(this.comboBoxPrevOwner.SelectedItem);
if (selected != "No")
{
textBoxLastOwnerName.Visible = true;
labelLastOwnerName.Visible = true;
textBoxLastOwnerFone.Visible = true;
labelLastOwnerFone.Visible = true;
textBoxLastOwnerAddr.Visible = true;
labelLastOwnerAddr.Visible = true;
}
else
{
textBoxLastOwnerName.Visible = false;
labelLastOwnerName.Visible = false;
textBoxLastOwnerFone.Visible = false;
labelLastOwnerFone.Visible = false;
textBoxLastOwnerAddr.Visible = false;
labelLastOwnerAddr.Visible = false;
}
}
private void comboBoxVitalStatus_SelectedIndexChanged(object sender, EventArgs e)
{
string selected = this.comboBoxVitalStatus.GetItemText(this.comboBoxVitalStatus.SelectedItem);
if (selected != "Alive")
{
dateTimeDateOfDeath.Visible = true;
labelDateOfDeath.Visible = true;
textBoxCauseOfDeath.Visible = true;
labelCauseOfDeath.Visible = true;
}
else
{
dateTimeDateOfDeath.Visible = false;
labelDateOfDeath.Visible = false;
textBoxCauseOfDeath.Visible = false;
labelCauseOfDeath.Visible = false;
}
}
private void comboBoxRetained_SelectedIndexChanged(object sender, EventArgs e)
{
string selected = this.comboBoxRetained.GetItemText(this.comboBoxRetained.SelectedItem);
if (selected != "Yes")
{
dateTimeRelinquishedDate.Visible = true;
labelRelinquishedDate.Visible = true;
}
else
{
dateTimeRelinquishedDate.Visible = false;
labelRelinquishedDate.Visible = false;
}
}
private void textBoxUid_TextChanged(object sender, EventArgs e)
{
SqlCommand cmd1 = new SqlCommand("select top 1 * from dbMyBirds where db_Uid = '" + textBoxUid.Text + "'", connection);
cmd1.Parameters.AddWithValue("db_Uid", textBoxUid.Text);
SqlDataReader reader1;
connection.Open();
reader1 = cmd1.ExecuteReader();
if (reader1.Read())
{
labelResult.Text = "Found";
textBoxName.Text = reader1["db_Name"].ToString();
textBoxSpecies.Text = reader1["db_Species"].ToString();
comboBoxLegBandType.Text = reader1["db_LegBandType"].ToString();
textBoxLegBandID.Text = reader1["db_LegBandId"].ToString();
textBoxLegBandSize.Text = reader1["db_LegBandSize"].ToString();
comboBoxPrevOwner.Text = reader1["db_PrevOwner"].ToString();
textBoxLastOwnerName.Text = reader1["db_PrevOwnerName"].ToString();
textBoxLastOwnerFone.Text = reader1["db_PrevOwnerFone"].ToString();
textBoxLastOwnerAddr.Text = reader1["db_PrevOwnerAddr"].ToString();
comboBoxIsHybrid.Text = reader1["db_Hybrid"].ToString();
comboBoxRearedBy.Text = reader1["db_RearedBy"].ToString();
textBoxDisformaties.Text = reader1["db_Disformaties"].ToString();
comboBoxVitalStatus.Text = reader1["db_VitalStatus"].ToString();
dateTimeDateOfDeath.Text = reader1["db_DateDied"].ToString();
textBoxCauseOfDeath.Text = reader1["db_CauseOfDeath"].ToString();
comboBoxRetained.Text = reader1["db_Retained"].ToString();
dateTimeRelinquishedDate.Text = reader1["db_RelinquishedDate"].ToString();
dateTimeHatchDate.Text = reader1["db_HatchDate"].ToString();
dateTimeFledgeDate.Text = reader1["db_FledgeDate"].ToString();
comboBoxMaleParentHybrid.Text = reader1["db_MPisHybrid"].ToString();
textBoxMaleParentId.Text = reader1["db_MPUid"].ToString();
textBoxMaleParentSpecies.Text = reader1["db_MPSpecies"].ToString();
comboBoxHenParentHybrid.Text = reader1["db_FPisHybrid"].ToString();
textBoxHenParentId.Text = reader1["db_FPUid"].ToString();
textBoxHenParentSpecies.Text = reader1["db_FPSpecies"].ToString();
textBoxNotes.Text = reader1["db_Notes"].ToString();
}
else
{
resetInputs();
if (textBoxUid.Text == "")
{
labelResult.Text = "Live Search";
}
else
{
labelResult.Text = "Nothing Found";
}
}
connection.Close();
}
//Reset input fields if no results
private void resetInputs()
{
string dt2;
DateTime date2 = DateTime.Now;
dt2 = date2.ToShortDateString(); // display format: 15/07/2021
textBoxName.Text = "";
textBoxSpecies.Text = "";
comboBoxLegBandType.Text = "Select";
textBoxLegBandID.Text = "";
textBoxLegBandSize.Text = "";
comboBoxPrevOwner.Text = "Select";
textBoxLastOwnerName.Text = "";
textBoxLastOwnerFone.Text = "";
textBoxLastOwnerAddr.Text = "";
comboBoxIsHybrid.Text = "Select";
comboBoxRearedBy.Text = "Select";
textBoxDisformaties.Text = "";
comboBoxVitalStatus.Text = "Select";
dateTimeDateOfDeath.Text = dt2;
textBoxCauseOfDeath.Text = "";
comboBoxRetained.Text = "Select";
dateTimeRelinquishedDate.Text = dt2;
dateTimeHatchDate.Text = dt2;
dateTimeFledgeDate.Text = dt2;
comboBoxMaleParentHybrid.Text = "Select";
textBoxMaleParentId.Text = "";
textBoxMaleParentSpecies.Text = "";
comboBoxHenParentHybrid.Text = "Select";
textBoxHenParentId.Text = "";
textBoxHenParentSpecies.Text = "";
textBoxNotes.Text = "";
}
private void buttonInsert_Click(object sender, EventArgs e)
{
}
}
}
I have created a GUI in Visual Studio where I have two buttons. One button is used to show ip and second button is used to take that ip and run python script.
But I want to merge these both operations into only one button, that if clicked for the first time should show/take the ip, and when clicked a 2nd time, it should trigger the Python script and all that in single button click.
My code is:
private void button1_Click(object sender, EventArgs e)
{
var fileName = "C:\\test.txt";
var sr = new StreamReader(fileName);
string fileContent = sr.ReadToEnd();
var startBlock = "hello";
var endBlock = "exit";
var ip = ParseForIpRegex(fileContent, startBlock, endBlock);
myTextBox.Text = ip; //Change this to match your code
}
private readonly string IPV4_PATTERN = "[0-9.]";
private string ParseForIpRegex(string textToSearch, string startBlock, string endBlock)
{
var pattern = $#"{startBlock}\D*\s*({IPV4_PATTERN}+).*{endBlock}";
var ms = Regex.Match(textToSearch, pattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
if (ms.Groups.Count > 0)
{
return ms.Groups[1].Value;
}
return string.Empty;
}
private void button1_Click_1(object sender, EventArgs e)
{
var hostname = myTextBox.Text;
var username = textBox1.Text;
var password = textBox2.Text;
var psi = new ProcessStartInfo();
psi.FileName = #"C:\Python38\python.exe";
var script = #"C:pythonscript.py";
//var config_file = file_path;
psi.Arguments = $"{script} {hostname} {username} {password}";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
var errors = "";
var results = "";
MessageBox.Show("script processing");
using (var process = Process.Start(psi))
{
errors = process.StandardError.ReadToEnd();
results = process.StandardOutput.ReadToEnd();
}
Console.WriteLine("ERRORS:");
Console.WriteLine(errors);
Console.WriteLine();
Console.WriteLine("Results:");
Console.WriteLine(results);
if (errors != "")
{
MessageBox.Show(errors);
}
else
{
MessageBox.Show(results);
}
}
Please let me know how I can merge this both operation into one. That in one click 1st button operation will perform and after that 2nd in single click.
I suppose you need to keep all buttons, so you dont use args, just call the method:
private void button1_Click(object sender, EventArgs e)
{
//DO job
// simulate the second click
button1_Click_1(sender, e)
}
private void button1_Click_1(object sender, EventArgs e)
{
//you could test args to check if its coming from first button
}
The answer of Frenchy, or you can add 2 handers on the event...
depending your preference.
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += new System.EventHandler(this.button1_Click_1);
take note that one of the two the designer will add it for you.
So add the second at form_load event (or where u see fit)
Cheers
I am having an issue with my program. my program will let the user select a dropdown value and after they select the dropdown value the datagridview should load with the data from a table, and then the progress bar should start the percentage 1 to 100%. Now everything in my program works the datagridview loads correctly and everything else in the program. the progress bar also works and loads but the issue comes when the user selects the dropdow combobox the progress bar takes like 15 to 20 seconds to start. I would like it to right away.
Can you see my code and see what could be the issue to why the progress bar is not starting right away?
if you need more information please let me know.
namespace DatagridViewProgressBar
{
public partial class Form1 : Form
{
//datagridview, bindingsource, data_apapter global objects variables
private DataGridView dataGridView = new DataGridView();
private BindingSource bindingSource = new BindingSource();
private SqlDataAdapter dataAdapter = new SqlDataAdapter();
DataTable dt = new DataTable();
//class objects
Databases lemars = new Databases();
Databases schuyler = new Databases();
Databases detroitlakeskc = new Databases();
public Form1()
{
InitializeComponent();
// To report progress from the background worker we set this property
dbWorker = new BackgroundWorker();
dbWorker.DoWork += new DoWorkEventHandler(dbWorker_DoWork);
dbWorker.ProgressChanged += new ProgressChangedEventHandler(dbWorker_ProgressChanged);
dbWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(dbWorker_RunWorkerCompleted);
dbWorker.WorkerReportsProgress = true;
dbWorker.WorkerSupportsCancellation = true;
}
private void btn_Exit_Click(object sender, EventArgs e)
{
this.Close();
}
private void comboBox_Database_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox_Database.SelectedItem.ToString() == "LeMars21St")
{
if (dbWorker.IsBusy != true)
{
dbWorker.RunWorkerAsync();
}
}
}
private void GetTableToDataGridView()
{
//prgBar_DataGridViewLoading
DatabaseColumns Obj = new DatabaseColumns();
String SqlcmdString = #"SELECT invoice, shipment, Project, invoiceDateTB, CreatedDate, typeName, exportedDate, statusName, total, import_status, Time_Completed, ERROR_DESCRIPTION FROM dbo.AllInvoicesInReadyStatus";
SqlDataReader reader;
int progress;
using (SqlConnection conn = new SqlConnection(lemars._LeMarsConnectionString))
{
reader = null;
SqlCommand Sqlcmd = new SqlCommand(SqlcmdString, conn);
conn.Open();
reader = Sqlcmd.ExecuteReader();
if (reader.HasRows)
{
try
{
dt.Load(reader);
for (int i = 0; i < dt.Rows.Count; i++)
{
Obj.Invoice = dt.Rows[i]["invoice"].ToString();
Obj.Shipment = dt.Rows[i]["shipment"].ToString();
Obj.Project = dt.Rows[i]["Project"].ToString();
Obj.InvoiceDateTB = Convert.ToDateTime(dt.Rows[i]["invoiceDateTB"]);
Obj.CreatedDate = Convert.ToDateTime(dt.Rows[i]["CreatedDate"]);
Obj.TypeName = dt.Rows[i]["typeName"].ToString();
Obj.ExportedDate = Convert.ToDateTime(dt.Rows[i]["exportedDate"]);
Obj.StatusName = dt.Rows[i]["statusName"].ToString();
Obj.Total = Convert.ToDecimal(dt.Rows[i]["total"]);
Obj.ImportStatus = dt.Rows[i]["import_status"].ToString();
if (!Convert.IsDBNull(dt.Rows[i]["Time_Completed"]))
{
Obj.TimeCompleted = Convert.ToDateTime(dt.Rows[i]["Time_Completed"]);
}
Obj.ErrorDescription = dt.Rows[i]["ERROR_DESCRIPTION"].ToString();
progress = i * 100 / dt.Rows.Count;
dbWorker.ReportProgress(progress);
Thread.Sleep(500);
}
}
finally
{
conn.Close();
}
}
}
}
private void dbWorker_DoWork(object sender, DoWorkEventArgs e)
{
GetTableToDataGridView();
dbWorker.ReportProgress(100);
}
private void dbWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar_GetTasks.Value = e.ProgressPercentage;
// eg: Set your label text to the current value of the progress bar
lbl_PercentageCount.Text = (progressBar_GetTasks.Value.ToString() + "%");
}
private void dbWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
dataGridView_ShowAllData.DataSource = dt;
if (e.Cancelled)
{
MessageBox.Show("Process Cancelled.");
}
else if (e.Error != null)
{
MessageBox.Show("Error occurred: " + e.Error.Message);
}
else
{
MessageBox.Show("Successful Completion.");
}
//progressBar_GetTasks.Value = 0;
}
private void btn_CancelOperation_Click(object sender, EventArgs e)
{
if (dbWorker.IsBusy)
{
dbWorker.CancelAsync();
}
}
}
}
Doing dt.Load(reader); waits for the data to fully load before continuing, Get rid of that line and replace it with a while(reader.Read()) loop.
private void GetTableToDataGridView()
{
//prgBar_DataGridViewLoading
DatabaseColumns Obj = new DatabaseColumns();
String SqlcmdString = #"SELECT invoice, shipment, Project, invoiceDateTB, CreatedDate, typeName, exportedDate, statusName, total, import_status, Time_Completed, ERROR_DESCRIPTION FROM dbo.AllInvoicesInReadyStatus";
String CountcmdString = #"SELECT count(*) FROM dbo.AllInvoicesInReadyStatus";
SqlDataReader reader;
int progress;
int total;
using (SqlConnection conn = new SqlConnection(lemars._LeMarsConnectionString))
{
reader = null;
SqlCommand Sqlcmd = new SqlCommand(CountcmdString , conn);
conn.Open();
total = (int)Sqlcmd.ExecuteScalar(); //Get the total count.
Sqlcmd.CommandText = SqlcmdString;
using(reader = Sqlcmd.ExecuteReader()) //this should be in a using statement
{
while(reader.Read())
{
object[] row = new object[reader.VisibleFieldCount];
reader.GetValues(row);
LoadSingleRowInToTable(dt, row); //I leave this to you to write.
//You can just read directly from the reader.
Obj.Invoice = reader["invoice"].ToString();
Obj.Shipment = reader["shipment"].ToString();
Obj.Project = reader["Project"].ToString();
Obj.InvoiceDateTB = Convert.ToDateTime(reader["invoiceDateTB"]);
Obj.CreatedDate = Convert.ToDateTime(reader["CreatedDate"]);
Obj.TypeName = reader["typeName"].ToString();
Obj.ExportedDate = Convert.ToDateTime(reader["exportedDate"]);
Obj.StatusName = reader["statusName"].ToString();
Obj.Total = Convert.ToDecimal(reader["total"]);
Obj.ImportStatus = reader["import_status"].ToString();
if (!Convert.IsDBNull(reader["Time_Completed"]))
{
Obj.TimeCompleted = Convert.ToDateTime(reader["Time_Completed"]);
}
Obj.ErrorDescription = reader["ERROR_DESCRIPTION"].ToString();
//Only call report progress when the progress value changes.
var newProgress = i * 100 / total;
if(progress != newProgress)
{
progress = newProgress;
dbWorker.ReportProgress(progress);
}
//Thread.Sleep(500);
}
}
}
}
UPDATE: Here is a example based on Steve's deleted answer that shows a better solution without using a DataTable.
private void dbWorker_DoWork(object sender, DoWorkEventArgs e)
{
List<DatabaseColumns> data = GetTableToList();
if (data == null) //data will be null if we canceled.
{
e.Cancel = true;
}
else
{
e.Result = data;
}
dbWorker.ReportProgress(100);
}
private void dbWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("Process Cancelled.");
}
else if (e.Error != null)
{
MessageBox.Show("Error occurred: " + e.Error.Message);
}
else
{
dataGridView_ShowAllData.DataSource = e.Result; //use the result from thebackground worker, only use if not canceled or errored.
MessageBox.Show("Successful Completion.");
}
//progressBar_GetTasks.Value = 0;
}
private List<DatabaseColumns> GetTableToList()
{
List<DatabaseColumns> data = new List<DatabaseColumns>();
//prgBar_DataGridViewLoading
String SqlcmdString = #"SELECT invoice, shipment, Project, invoiceDateTB, CreatedDate, typeName, exportedDate, statusName, total, import_status, Time_Completed, ERROR_DESCRIPTION FROM dbo.AllInvoicesInReadyStatus";
String CountcmdString = #"SELECT count(*) FROM dbo.AllInvoicesInReadyStatus";
using (SqlConnection conn = new SqlConnection(lemars._LeMarsConnectionString))
{
SqlCommand Sqlcmd = new SqlCommand(CountcmdString, conn);
conn.Open();
var total = (int)Sqlcmd.ExecuteScalar();
Sqlcmd.CommandText = SqlcmdString;
int i = 0;
int progress = 0;
using (SqlDataReader reader = Sqlcmd.ExecuteReader()) //this should be in a using statement
{
while (reader.Read())
{
if (dbWorker.CancellationPending)
{
//Exit early if operation was canceled.
return null;
}
DatabaseColumns Obj = new DatabaseColumns();
//You can just read directly from the reader.
Obj.Invoice = reader["invoice"].ToString();
Obj.Shipment = reader["shipment"].ToString();
Obj.Project = reader["Project"].ToString();
Obj.InvoiceDateTB = Convert.ToDateTime(reader["invoiceDateTB"]);
Obj.CreatedDate = Convert.ToDateTime(reader["CreatedDate"]);
Obj.TypeName = reader["typeName"].ToString();
Obj.ExportedDate = Convert.ToDateTime(reader["exportedDate"]);
Obj.StatusName = reader["statusName"].ToString();
Obj.Total = Convert.ToDecimal(reader["total"]);
Obj.ImportStatus = reader["import_status"].ToString();
if (!Convert.IsDBNull(reader["Time_Completed"]))
{
Obj.TimeCompleted = Convert.ToDateTime(reader["Time_Completed"]);
}
Obj.ErrorDescription = reader["ERROR_DESCRIPTION"].ToString();
//Add the object to the list.
data.Add(Obj);
//Only call report progress when the progress value changes.
var newProgress = i * 100 / total;
if (progress != newProgress)
{
progress = newProgress;
dbWorker.ReportProgress(progress);
}
i++;
}
}
}
return data;
}
Something I had when doing my first backgroundWorker, was the GUI locking up. I made the mistake of trying to hand out every result (primnumbers in a range from 2 to selected bound) as it was found via report progress. If I had a long enough operation (it did not happen if the operation was short) I ended up overloading and locking up the GUI with write operations, making it appear I never actually added multithreading.
Now I noticed this line:
progress = i * 100 / dt.Rows.Count;
You run the progress code (and update the bar) every loop itteration, even if the percentage did not actually change. If you process 1 million itterations, that is 10000 redraws without the value actually changing. This might slow down later as hits become rarer or the GC starts interferring with optimal performance of the task so the GUI thread has "time to catch up".
You should check if the value actually changed, before writing it to the GUI. Latest in the ProgressReporting Event. But it might be possible to do something back in the loop itself.
I made some example code to showcase what I call the "GUI write overhead" problem:
using System;
using System.Windows.Forms;
namespace UIWriteOverhead
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int[] getNumbers(int upperLimit)
{
int[] ReturnValue = new int[upperLimit];
for (int i = 0; i < ReturnValue.Length; i++)
ReturnValue[i] = i;
return ReturnValue;
}
void printWithBuffer(int[] Values)
{
textBox1.Text = "";
string buffer = "";
foreach (int Number in Values)
buffer += Number.ToString() + Environment.NewLine;
textBox1.Text = buffer;
}
void printDirectly(int[] Values){
textBox1.Text = "";
foreach (int Number in Values)
textBox1.Text += Number.ToString() + Environment.NewLine;
}
private void btnPrintBuffer_Click(object sender, EventArgs e)
{
MessageBox.Show("Generating Numbers");
int[] temp = getNumbers(10000);
MessageBox.Show("Printing with buffer");
printWithBuffer(temp);
MessageBox.Show("Printing done");
}
private void btnPrintDirect_Click(object sender, EventArgs e)
{
MessageBox.Show("Generating Numbers");
int[] temp = getNumbers(1000);
MessageBox.Show("Printing directly");
printDirectly(temp);
MessageBox.Show("Printing done");
}
}
}
I have a traffic exchange website and I want to convert it into an windows application using C# winform with Awesomium 1.7.5.
The basic setup is ready but there is a problem with Awesomium.
After visiting a few websites slows down and the freezes entirely ( Not Responding ).
public Form1()
{
InitializeComponent();
Text = "Traffic Exchange";
WindowState = FormWindowState.Maximized;
timer1 = new System.Windows.Forms.Timer();
timer1.Tick += new EventHandler(timer1_Tick);
int user_id = Properties.Settings.Default.user_id;
string user_id_s = user_id.ToString();
toolStripLabel2.Text = user_id_s;
if (Properties.Settings.Default.user_id == 0)
{
toolStripLabel3.Visible = true;
toolStripButton3.Visible = false;
}
else
{
toolStripButton3.Visible = true;
toolStripLabel3.Visible = false;
}
}
private void toolStripButton3_Click_1(object sender, EventArgs e)
{
// starting the traffic traffic exchange
LoadUrl();
StartTimer();
}
private void LoadUrl()
{
try
{
string MyConnection2 = "*******";
string Query = "select * from ****** where status = 1 AND credits > 5 ORDER BY rand() LIMIT 1";
MySqlConnection MyConn2 = new MySqlConnection(MyConnection2);
MySqlCommand MyCommand2 = new MySqlCommand(Query, MyConn2);
MyConn2.Open();
using (MySqlDataReader DR = MyCommand2.ExecuteReader())
{
while (DR.Read())
{
string WebURL = Convert.ToString(DR.GetValue(*));
string WebSurfSec = Convert.ToString(DR.GetValue(*));
int result = Convert.ToInt32(WebSurfSec);
int sec_to_mil = result * 1000;
toolStripLabel5.Text = WebSurfSec;
//toolStripStatusLabel2.Text = result.ToString();
//toolStripStatusLabel3.Text = sec_to_mil.ToString();
webControl3.Source = new Uri(WebURL);
toolStripTextBox1.Text = WebURL;
toolStripLabel6.Text = toolStripTextBox1.Text;
timer1.Interval = sec_to_mil; // in miliseconds
}
}
MyConn2.Close();
// WebCore.ReleaseMemory();
// webControl3.Update();
// Thread.Sleep(500);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
LoadUrl();
}
private void StartTimer()
{
timer1.Start();
}
So LoadUrl() it's a loop. When the app is started loads in the traffic exchange website, a little bit slow but it works and you can go form a page to another without freezing but when the exchange is in action ( LoadUrl() ) after 5 minutes the app is dead.
I've been searching for a solution all day and ended up with nothing, couldn't find a solution the problem.
The timer should not be recreated each time you loop. What is happening is that you are creating multiple event handlers each time you loop. Creating the handler once in the constructor and starting the timer in the button click routine is the right way.
You can change the interval inside the loop, but avoid adding another Start() method call there.
I am not sure which parameters i am meant to pass when calling the function in this If/Else statement.
The If/Else statement is calling 1 of 2 functions, Online_Version or Offline Version.
Code is as follows:
public void Form1_Load(object sender, EventArgs e)
{
if (MessageBox.Show("Would you like to run the Event Register?", "Registration Selection", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
label5.Text = "Event Registration";
textBox1.Select();
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
var fileSave = new FileStream(fullFileName, FileMode.Create);
fileSave.Close();
OfflineRegister();
}
else
{
label5.Text = "ICAS Register";
textBox1.Select();
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
var fileSave = new FileStream(fullFileName, FileMode.Create);
fileSave.Close();
OnlineRegister();
}
}
public void Online_Register(object sender, KeyPressEventArgs e)
{
OnlineRegister();
}
public void Offline_Register(object sender, KeyPressEventArgs e)
{
OfflineRegister();
}
public void OnlineRegister()
{
SqlConnection DBConnection = new SqlConnection("Data Source=DATABASE;Initial Catalog=imis;Integrated Security=True");
SqlCommand cmd = new SqlCommand();
Object returnValue;
string txtend = textBox1.Text;
string lastTwoChars = txtend.Substring(txtend.Length - 1);
if (textBox1.Text.Length != 6 && e.KeyChar != '*') return;
//cmd.CommandText = ("SELECT last_name +', '+ first_name +'\t ('+major_key+')\t' from name where id =#Name");
cmd.CommandText = ("SELECT last_name +', '+ first_name from name where id =#Name");
cmd.Parameters.Add(new SqlParameter("Name", textBox1.Text.Replace(#"L", "")));
cmd.CommandType = CommandType.Text;
cmd.Connection = DBConnection;
//Time = DateTime.Now.ToString("HH:mm");
//TimeIn = "Time In: ";
//TimeOut = "Time Out: ";
returnValue = cmd.ExecuteScalar() + "\t (" + textBox1.Text.Replace(#"L", "") + ")";
DBConnection.Close();
if (listBox1.Items.Contains(returnValue))
{
for (int n = listBox1.Items.Count - 1; n >= 0; --n)
{
string removelistitem = returnValue.ToString();
if (listBox1.Items[n].ToString().Contains(removelistitem))
{
listBox1.Items.RemoveAt(n);
//listBox1.Items.Add(removelistitem + " " + 'TimeOut' + 'Time');
}
}
}
else
listBox1.Items.Add(returnValue);
textBox1.Clear();
System.IO.StreamWriter sw = new System.IO.StreamWriter(fullFileName);
foreach (object item in listBox1.Items)
sw.WriteLine(item.ToString());
sw.Flush();
sw.Close();
if (listBox1.Items.Count != 0) { DisableCloseButton(); }
else
{
EnableCloseButton();
}
label6.Text = "Currently " + listBox1.Items.Count.ToString() + " in attendance.";
e.Handled = true;
}
public void OfflineRegister()
{
Object returnValue;
string txtend = textBox1.Text;
returnValue = textBox1.Text.Replace(#"*", "");
if (e.KeyChar != '*') return;
{
if (listBox1.Items.Contains(returnValue))
{
for (int n = listBox1.Items.Count - 1; n >= 0; --n)
{
string removelistitem = returnValue.ToString();
if (listBox1.Items[n].ToString().Contains(removelistitem))
{
//listBox1.Items.RemoveAt(n);
}
}
}
else
{
listBox1.Items.Add(returnValue);
textBox1.Clear();
System.IO.StreamWriter sw = new System.IO.StreamWriter(fullFileName);
foreach (object item in listBox1.Items)
sw.WriteLine(item.ToString());
sw.Flush();
sw.Close();
if (listBox1.Items.Count != 0) { DisableCloseButton(); }
else
{
EnableCloseButton();
}
label6.Text = "Currently " + listBox1.Items.Count.ToString() + " in attendance.";
e.Handled = true;
}
}
}
Any help is appreciated!
What you should do is take the code ouf of the Online_Register/Offline_Register event handlers and put it in a different methods called: OnlineRegister and OfflineRegister for example, that way you can do this:
public void Form1_Load(object sender, EventArgs e)
{
if (MessageBox.Show("Would you like to run the Event Register?","Registration Selection", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
label5.Text = "Event Registration";
textBox1.Select();
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
var fileSave = new FileStream(fullFileName, FileMode.Create);
fileSave.Close();
OfflineRegister();
}
else
{
label5.Text = "ICAS Register";
textBox1.Select();
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
var fileSave = new FileStream(fullFileName, FileMode.Create);
fileSave.Close();
OnlineRegister();
}
}
public void Online_Register(object sender, KeyPressEventArgs e)
{
OnlineRegister();
}
public void Offline_Register(object sender, KeyPressEventArgs e)
{
OfflineRegister();
}
public void OnlineRegister()
{
// Do Stuff
}
public void OfflineRegister()
{
// Do Stuff
}
This is of course assuming that you actually need the KeyPress event handlers.
Explanation
The bottom of the code above shows two methods which I just created. These can be called from within your event handlers and on the Form1_Load event. This is useful as you won't have to repeatedly paste the same code over and over again.
Improvements
You could improve your current scenario by taking the Register code and putting it inside a different class, maybe called, RegisterHelper or something, which serves the purpose of providing logic for Registering users.
Furthermore, you could give your Form a name that's a little more appropriate, instead of Form1.
Check the FullFileName variable value, methods looks perfect. Always segregate the UI and functional events.