I've searched through stackoverflow but cannot find the answer. I don't know if I could make this question clearly. I'm not an English-speaking person anyway =.=
I'm using c# and visual studio 2010 to develop.
I'm making a Form for user to login, I would like this form test sql server connection during load event.
It seems easy, the code is:
private void testDBconnection()
{
label3.Text = "Connecting to Database Server......";
SqlServerConnection ssc = new SqlServerConnection();
bool conOK = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword,
5));
if (conOK)
{
label3.Text = "";
}
else
{
label3.Text = "Database connection failed";
button1.Enabled = false;
}
}
I put this method in Form_Load event.
But in runtime, this process start even before this form shows. And the validation could last for 15 seconds by default(I set it to 5 but it also takes time). If the connection has some problem, it will display like the programe failed to open, but it will shown after it failed to connect to database.
My intention is tell the user by Label3 displaying "Connecting to Database Server......", and tell user if connection failed.
I was trying to find Form Event like "Loaded_Complete", or "Loaded"(I found Form_Closed though), but I couldn't.
I guess it has something to do with thread, programe sleeping, or else. I hope someone could help me on this. Thanks a lot guys!
I would use a BackgroundWorker this way. That will defer the database check operation, and the form load will not be locked by it.
label3.Text = "Connecting...";
button1.Enabled = false;
var bkw = new BackgroundWorker();
bkw.DoWork += (s, ev) =>
{
SqlServerConnection ssc = new SqlServerConnection();
ev.Result = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword, 5));
};
bkw.RunWorkerCompleted += (s, ev) =>
{
if ((bool)ev.Result == true)
{
label3.Text = "Connected";
button1.Enabled = true;
}
else
{
label3.Text = "Database connection failed";
}
bkw.Dispose();
};
bkw.RunWorkerAsync();
However, this would require some exception handling. If an exception occurs in the DoWork event, then you can check in the RunWorkerCompleted event wether ev.Error is null or not (it contains the exception) and react accordingly.
Use timer.
In form load event start the timer(set interval to 2 sec or what ever you want). As timer ticks call your connection method. At the starting of your testDBconnection() method, stop the timer and dispose it because you don't need it any more.
You should not be using the Form_Load event to fire events when a form loads, you should override the OnLoad() method instead, that way you control when the code gets fired (it's possible for multiple subscribers to be listening to Form_Load and you don't know what order they will run in).
The quickest and dirtiest way of getting the screen to refresh is to Add
Application.DoEvents();
After changing the label, this forces the screen to update. In general though this is bad practice and the background thread above would be a better solution long term.
Related
My first question to this forum, so please be kind :D
I'm building a desktop application in C# that should read data from a Raspberry Pi and show it (values, charts...). The MainForm.cs has a menu strip where I can call a child form, ConnectionSetupForm.cs where I can enter the database connection values (db user, password, table, host, port, etc.) which are stored as Properties.Settings.Default.xxx (System.Configuration).
When I'm closing this child form with a save button, I want the MainForm to get this information and refresh. This works, but only after I restart the application, but it should be when the FormClosing or FormClosed event of the child form happens (in my example the MessageBox.Show() never occurs).
What am I missing? I have no errors and no warnings.
MainForm calls the child form ConnectionSetupForm:
private void showConnectionForm(object sender)
{
connectionSetupForm = new ConnectionSetupForm();
connectionSetupForm.MdiParent = this.ParentForm;
connectionSetupForm.StartPosition = FormStartPosition.CenterParent;
connectionSetupForm.ShowDialog();
connectionSetupForm.FormClosed += new FormClosedEventHandler(ConnectionForm_FormClosed);
}
private void ConnectionForm_FormClosed(object sender, FormClosedEventArgs e)
{
Properties.Settings.Default.Save();
Properties.Settings.Default.Reload();
MessageBox.Show("Closed"); // is never called, so this method is never called...
// actually, I want to do some stuff here, e.g.:
this.Text = Properties.Settings.Default.ApplicationName; // name is changed after restart only
connectionSetupForm = null;
}
This looks to be a simple mis-ordering of a couple lines. The connectionSetupForm.ShowDialog(); line is actually a call to a blocking function. This means nothing past this line will execute until AFTER your dialog closes. Because you add the FormClosed event handler after the form has already closed, the ConnectionForm_FormClosed() function never gets called.
Try simply putting the FormClosed event handler before the connectionSetupForm.ShowDialog(); line.
private void showConnectionForm(object sender)
{
connectionSetupForm = new ConnectionSetupForm();
connectionSetupForm.MdiParent = this.ParentForm;
connectionSetupForm.StartPosition = FormStartPosition.CenterParent;
connectionSetupForm.FormClosed += new FormClosedEventHandler(ConnectionForm_FormClosed);
connectionSetupForm.ShowDialog();
}
I'm building a windows form application that stores employee information records in a database, including SSN. Next to the textbox where the SSN is input is requested, I have a checkbox that when clicked, shows me the full SSN instead of the last four digits. To ensure that only an administrator is accessing this information, I created a prompt form connected to a MS SQL DB that stores an admin password and would like to ask the user for a password for security purposes. Also, i'd like to be able to call this form whenever needed. I successfully implemented it but would like to add a feature that allows for 3 tries. Is there a way to stop the program execution and keep prompting the user for input in a textBox?
output is a variable that stores the result of the 'SELECT' query that gets the password.
confirmation is the Accept Button.
The only option i could think of forcing input was calling a new form. Only problem is, this code is inside the form and my gut tells me that's not the answer to this problem. I must be missing something.
confirmation.Click += (sender, e) => {
//If Password is correct.
if (textBox.Text == output)
{
isCorrect = true;
Pprompt.Close();
}
else
{
isCorrect = false;
//While the password is incorrect.
while (isCorrect == false)
{
//textBox.Text = "";
if (textBox.Text == output)
{
isCorrect = true;
Pprompt.Close();
break;
}
tryCount++;
if (tryCount == 3)
{
MessageBox.Show("Access Denied.");
break;
}
}
}
}
What I'd like to happen is for the form to keep asking me for input until the try limit is exceeded.
You cannot have the loop inside the click handler, because the UI freezes while it is running and the user does not get the opportunity make any entries.
Process only one entry and process the next when the user clicks the button again.
confirmation.Click += (sender, e) => {
if (textBox.Text == output) // Password is correct.
{
isCorrect = true;
Pprompt.Close();
}
else
{
isCorrect = false;
textBox.Text = "";
tryCount++;
if (tryCount == 3)
{
MessageBox.Show("Access Denied.");
Pprompt.Close();
}
}
}
Unless you are using multi-threading or async/await, the following is true:
Winforms is event based. I.e., if no event handler is running, no code is running.
If code (i.e. an event handler) is running, the user interface (UI) is frozen and the user cannot make any input. He cannot enter text or click any buttons, cannot scroll lists and cannot resize or move the window.
While an event handler is running, no other event handler will ever be called. I.e., an event handler will never be interrupted by another one. This prevents you from having to deal with multi-threading issues unless you are using multi-threading explicitly.
If an event should be fired (e.g. a timer tick) while an event handler (e.g. a button click handler) is running, the execution of the event handler associated to this new event will be deferred until after the first event handler returns.
Hi all I'm still new to the c# events and timers but it seems I have a bug that baffles me despite following seemingly working code online. I have a simple search function that is triggered after a timer elapses. Before that function triggers I set the result title to "Search in progress..." and at the end of the process i expect it to change to "1152 results found". But the label doesn't change eventhough in debug i hit the code sets it and i even see that the searchresultTitle.Text value is changed and the "list" actually contains 1152 items. The website just doesnt reflect it, is there something wrong with the way I setup the timers or am I missing something?
protected void StartSearchClick(object sender, EventArgs ev)
{
String textVal = Request["SearchBox"];
textVal = textVal.Replace('*', '_');//to support * as wildcard
String publicChoice = PublicChoice.SelectedValue;
int iChoiceVal = 1;
Int32.TryParse(publicChoice, out iChoiceVal);
SearchResultTitle.Text = "Search in progress...";
System.Timers.Timer aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += (s, e) => ReadPublishedLessons(textVal, iChoiceVal);
aTimer.AutoReset = false;
aTimer.Start();
}
private void ReadPublishedLessons(string namePart, int iPublic)
{
//null check
if (namePart == null)
return;
eon.LessonInfo[] list = WsAdmin.GetLessonList(namePart, iPublic);
SearchResultTitle.Text = list.Length + " results found";
}
Answered by Bharadwaj in the comments...
In case of asp.net, the html is sent back to the client side only after a post back or a partial post back. At the end of your event trigger call, the html which is ready is already reached to the client with Search in progress... message. But when you try to change the value of label, it is changing and it is still at server only. – Bharadwaj Jul 15 '16 at 4:45
I created an AJAX Timer on my C# ASP.NET page to check for a record in a database.
When the record is not found I would like for the DB polling to continue.
Currently it is blowing up when no records are found.
It does work great when the record is found, then I just look for a correct status.
I have 2 questions.
1.) How can I continue polling when there is no record found.
2.) How can I get the timer to stop polling after 5 minutes and display a message?
Here is some of my code:
protected void Timer1_Tick(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(8000);
string fileName = ViewState["FileName"].ToString();
DBACCT account = new AccountMDB();
DataTable dt = account.getSTS(fileName);
String status = dt.Rows[0]["sts"].ToString();
Label2.Text = status;
if (dt.Rows.Count == 0)
{
// restart timer?
}
if (status == "C")
{
Timer1.Enabled = false;
Label2.Text = "File processed correctly";
}
if (status == "E")
{
Timer1.Enabled = false;
Label2.Text = "File processed with Errors";
}
}
First, you shouldn't be getting the status until AFTER you've checked the row count (which is why it is probably blowing up).
Second, why are you sleeping inside of the timer method? Why not just have the timer go off every 8 seconds instead? Setting the 'interval' to 8000 should do the trick.
Now, to answer your questions.
1.) Aren't AJAX timers set up to auto repeat? If they are, it should automatically be running this code every 8 seconds, if you make the change specified earlier. If they are not, you'll have to do some research on how to make them repeat.
2.) The easiest way would be to just create another timer that goes off after 5 minutes which will disable both timers as well as print the message.
I have a TextBox with a TextChanged event wired up. In the end it is making a query to a SQL database, so I want to limit the number of queries.
I only want to make the query if the user hasn't pressed a key in say .. 300 milliseconds or so. If for some reason the previous query is still executing, I would need to cancel that, and then issue a new query.
Create a System.Windows.Forms.Timer and reset it (e.g. stop then start it) after every keypress. If the timer event is triggered, disable the timer.
Use the Reactive Framework to trigger on a sequence of events. I'm not sure exactly how this would work, but you can read up on it here (Reactive Extensions for .NET) and see if it will fulfill your needs. There are a bunch of examples here too: Examples. The "Throttling" example may be what you're looking for.
1) Create a timer.
2) Create a handler for the Tick event of your timer. On each tick, check to see if enough idle time has elapsed, and if it has, STOP the timer and execute the query.
3) Whenever a keypress occurs on that textbox, RESTART the timer.
Add a second actionlistener that gets called whenever the user presses any key and when it gets called save the current time to a global variable. Then whenver your TextChanged event gets called it checks to see the time difference between the global variable and the current time.
If the difference is less than 300 milliseconds then start a timer to execute the query after 300 milliseconds. Then if the user presses another key it resets the timer first.
Thanks to #Brian's idea and this answer , I came up with my own version of using a timer to handle this issue. This worked fine for me. I hope it helps the others as well:
private Timer _tmrDelaySearch;
private const int DelayedTextChangedTimeout = 500;
private void txtSearch_TextChanged(object sender, EventArgs e)
{
if (_tmrDelaySearch != null)
_tmrDelaySearch.Stop();
if (_tmrDelaySearch == null)
{
_tmrDelaySearch = new Timer();
_tmrDelaySearch.Tick += _tmrDelaySearch_Tick;
_tmrDelaySearch.Interval = DelayedTextChangedTimeout;
}
_tmrDelaySearch.Start();
}
void _tmrDelaySearch_Tick(object sender, EventArgs e)
{
if (stcList.SelectedTab == stiTabSearch) return;
string word = string.IsNullOrEmpty(txtSearch.Text.Trim()) ? null : txtSearch.Text.Trim();
if (stcList.SelectedTab == stiTabNote)
FillDataGridNote(word);
else
{
DataGridView dgvGridView = stcList.SelectedTab == stiTabWord ? dgvWord : dgvEvent;
int idType = stcList.SelectedTab == stiTabWord ? 1 : 2;
FillDataGrid(idType, word, dgvGridView);
}
if (_tmrDelaySearch != null)
_tmrDelaySearch.Stop();
}