I'm new to C#. I have two textboxes in a form and a button. When I click the button, I want the value 1 to be put into textbox1 and then the squareroot calculated and put into textbox2. I then want the code to loop for each number between 1-20 and place the respective values in the textboxes. I am simply writing this code just to get used to function calls. My code is below but it doesn't seem to do anything:-
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
for (int initialVal = 1; initialVal >= 20; initialVal++)
{
textBox1.Text = initialVal.ToString();
int sum = calculation(initialVal);
textBox2.Text = sum.ToString();
System.Threading.Thread.Sleep(500);
}
}
static int calculation(int x)
{
int sum;
while (x <= 20)
{
sum = x * x;
x++;
return sum;
}
return 0;
}
}
}
Any suggestions on what is wrong with it?
Two things:
1)
for (int initialVal = 1; initialVal >= 20; initialVal++)
This will never do anything because the exit condition is met - you probably meant initialVal <= 20
2) You need to use a background thread - otherwise your GUI won't update until your button1_Click handler is completely finished. E.g. have a look at the BackgroundWorker class.
Your for-loop will never be executed since its condition is not satisfied:
initialVal >= 20
Change it to
initialVal <= 20
to execute the loop 20 times.
Change the loop as suggested by others.
And, for this line, I think you can simply do
int sum = initialVal * initialVal ;
You don't need the calculate to square a number, and that function doesn't do anything meaningful anyway.
Calling Sleep in the GUI can make your app unresponsive, so it's better to use a background thread or a timer. A timer is easier. First, in design view, just drag and drop a Timer (it's in the Components section of your toolbox) onto the form. Set the Interval property to 500. Then double-click it, and put your update code in there. Note you don't need the loop; you just need some code to tell it to increment initialVal with each tick and stop at 20:
private void timer1_Tick(object sender, EventArgs e) {
textBox1.Text = initialVal.ToString();
int sum = calculation(initialVal);
textBox2.Text = sum.ToString();
if (initialVal++ == 20)
timer1.Enabled = false;
}
Now change your button_click code to simply kick of the timer:
private void button1_Click(object sender, EventArgs e) {
initialVal = 1;
timer1.Enabled = true;
}
Finally make initialVal as a member variable since both functions need access to it:
public partial class Form1 : Form {
int initialVal;
Related
I made a sample project. Where every 10 second it do some function. But when I try to show a timer tick in label it always stuck, and jump to certain second (eg: stuck at 9s and suddenly jump to 12s). What i want to ask,
Is my function run properly ?
Is my tick, skipped a few ms ? (it will overlap with my function)
How do I run it as a thread ?
My code
private void button2_Click(object sender, EventArgs e)
{
timer1.Start();
}
int x = 0;
private void timer1_Tick(object sender, EventArgs e)
{
x += 1;
label1.Text = x.ToString();
if (x % 10 == 0)
{
addpoint();
//MessageBox.Show("success");
}
}
how to keep my label1.text keep updating, while do addpoint() function
Note:
I have set timer1 interval = 1000
update
i test it with this.
public void addpoint()
{
string x = #"c:\test\a.txt";
string text = "haiaiaia";
using (FileStream fs = new FileStream(x, FileMode.Create))
{
Byte[] xx = Encoding.ASCII.GetBytes(text);
fs.Write(xx, 0, xx.Length);
}
Messagebox.show("Created !");
}
It looks like your using a Windows.Forms.Timer which is executed on the main thread. The advantage is that you don't need to call Invoke, the disadvantage is that addpoint is also executed on the main thread and hence blocks your GUI from update, when in the mean time the next tick events are fired.
You can verify it be replacing the call of addpoint with Thread.Sleep(3000) and you will experience the same behaviour.
What you could do is to try and run the method on another thread:
private void timer1_Tick(object sender, EventArgs e)
{
x += 1;
label1.Text = x.ToString();
if (x % 10 == 0)
{
Thread t = new Thread(addpoint);
t.Start();
}
}
This should avoid the blocking of the GUI.
Disclaimer:
It is important to know what you actually do in addpoint, because this solution might lead to race condition and wrong functioning of the method. For example if you are using class variables in it, and if the possibility exists that a second thread can be started while the first has not finished yet! Be aware.
I'm new to C# and i have a problem ... when i run my windows form application and press start button, during runtime i can't do anything with the form (close, minimize, move, ...) but when it's done i can close the form.
What should i do to solve it?
using System;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication10
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void c1Button1_Click(object sender, EventArgs e)
{
for ( int i = 0; i < 100; i++)
{
c1RadialGauge1.Value = i;
textBox1.Text = i.ToString();
textBox1.Update();
c1Gauge1.Refresh();
Thread.Sleep(100);
}
}
}
}
Since your button handler is running in the UI thread until it is finished, your UI blocks and you can't do anything else with that.
One solution to that would be to make the handler async and use await a Task.Delay() instead of using Thread.Sleep():
private async void c1Button1_Click(object sender, EventArgs e)
{
c1Button1.Enabled = false; // avoid multiple clicks
for ( int i = 0; i < 100; i++)
{
c1RadialGauge1.Value = i;
textBox1.Text = i.ToString();
textBox1.Update();
c1Gauge1.Refresh();
await Task.Delay(100);
}
c1Button1.Enabled = true; // allow further clicks
}
The compiler translates this code into a state machine. At the await keyword, the control flow is returned to the caller (the UI) and resumed when Task.Delay() has finished. So while Task.Delay() runs, the UI thread has time to react on other events (e.g. user interaction).
I added two lines to disable the button while the whole thing is running, so that the user can't start this several times.
But this is only possible using .NET 4.5 or newer. Read this for more information about async/await.
If you have to use an older .NET framework, you may use a BackgroundWorker instead.
I am making a simple wpf application. It has a button and a textbox and when you click the button it should update the textbox the whole time(see code). I have 3 problems:
It doesn't update the textbox in the loop.
When I click the button It is stuck and I can't close the application(only with taskmanager and stop debugging).
If i leave the textbox stuck and do not close it. After a minute or so I get this error: ContextSwitchDeadlock occurred with the break mode screen.
I have tried to solve the problem by searching on the internet but I didn't succeed. I hope you guys are able to solve it:). And the code is here:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Play_Click(object sender, RoutedEventArgs e)
{
int x = RandomNumber();
}
private string TextboxData;
private int RandomNumber()
{
int x = 0;
int i = 0;
Random rng = new Random();
do
{
x = rng.Next(1, 1000000);
i++;
TextboxData += "\r\nAl zo vaak :O" + i; //the rng loop
textBox.Text = TextboxData;
}
while (x != 1);
TextboxData += "\r\nHij heeft zo vaak geprobeerd 1 te halen " + i;
textBox.Text = TextboxData + Environment.NewLine;
return x;
}
}
The problem is that all your actions are made in main GUI thread.
That means that your program can't redraw interface because it's busy executing code in loop.
In order to achieve desired results you need to execute your loop asynchronous. But we must keep in mind that GUI should be updated only from GUI thread( it's framework requirement).
Due to quick calculations the texbox will be updated too often. You may consider using Thread.Sleep(100).
Here's solution:
private async void Play_Click(object sender, RoutedEventArgs e)
{
int x = await RandomNumber();
}
private async Task<int> RandomNumber()
{
int x = 0;
int i = 0;
string text = string.Empty;
Random rng = new Random();
// This will start work in background. Leaving GUI thread to it's own tasks.
await Task.Factory.StartNew(() =>
{
do
{
x = rng.Next(1, 1000000);
i++;
text = "\r\nAl zo vaak :O" + i.ToString(); //the rng loop
// This will invoke textbox update in GUI thread satisfying update requirement.
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(() => { textBox.AppendText(text); }));
// We will make it slower in order to see updates at adequate rate.
Thread.Sleep(100);
}
while (x != 1);
});
// thanks to await we will have this code executed after we found our x==1.
text = "\r\nHij heeft zo vaak geprobeerd 1 te halen " + i;
textBox.AppendText(text);
return x;
}
Don't forget to add following usings:
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
EDIT: I don't know why you want to have return value from RandomNumber() (it will always be 1. so it's pontless). But to handle that correctly we need to add async to our signatures in order to use await so we could get a value, execute code after awaited block and return result.
It's a pretty complicated topic, which I will only mention here in order to have correct solution. If you're interested - google '.net async await'. But I suggest to leave it for future :)
Also, I removed TextBoxData field and replaced it with local variable and used textbox.AppendText() as #KevinKal suggested.
I need a little help with a Random Number Guessing Game in visual studio. I got the brunt of the code down but I am having troubles with the Random number generator and getting the random number to port into the click events. As always, I don't really need code but some guidance and/or explanations as to what I am doing wrong and if there is a more effecient way to do things in the beginner phases of learning. Below is my code, the comments are the parts where I am having troubles. Thanks for any help as the help I've recieved to date as been phenominal.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace LAB6B
{
public partial class game : Form
{
public game()
{
InitializeComponent();
//Generate Random number between 1 and 100
//Not sure if there is a better way?
Random rand1 = new Random();
int num1 = rand1.Next(1,50);
int num2 = rand1.Next(1,50);
int answer = num1 + num2;
}
private void evaluate_Click(object sender, EventArgs e)
{
int count = 0;
int choice = Convert.ToInt32(guess);
if (guess.Text != string.Empty)
{
// set counter to keep track of how many tries
// should this be done by a loop or will it count without a loop?
count++;
//compare user input against random number
//Can’t import the random number for comparision
if (choice < answer)
{
Evaluate.Visible = false;
lblMessage.Visible = true;
lblMessage.Text = "Too Low!";
Clear.Visible = true;
BackColor = Color.LightSeaGreen;
}
else if (choice > answer)
{
Evaluate.Visible = false;
lblMessage.Visible = true;
lblMessage.Text = "Too High!";
Clear.Visible = true;
BackColor = Color.SlateBlue;
}
else
{
//Display correct message along with how many times it took to get it
MessageBox.Show(" Eso es CORRECTO! It took you {0} tries. ", count);
}
}
}
private void Clear_Click(object sender, EventArgs e)
{
guess.Text = "";
Evaluate.Visible = true;
lblMessage.Visible = false;
Clear.Visible = false;
BackColor = Color.PowderBlue;
}
}
}
As the rand1 and answer variables are defined within the constructor, you can only access them in the constructor. Defining answer on the class level will solve most of the problems, as you will be able to access it both from the constructor and the click handlers, like this:
private int answer;
private int count;
public game()
{
InitializeComponent();
//Generate Random number between 1 and 100
Random random= new Random();
// no need for num1 and num2, it's just as random
answer = random.Next(1,101);
}
I think you have an issue of scope. The "answer" variable is declared inside your constructor, so it will not be visible to the code inside evaluate_Click(…).
Looks like you need to declare answer as a class variable. When you declare a variable in a constructor, it's still local to that method and not available to other methods.
I do not really know what you want answered, but an obvious error is that you must define your count variable as a member variable in order to keep track of the number of tries. As it is now, the count will always be initialized as zero each time the user presses the button.
First of, you need to declare your variable answer in the page level so it can be used by other page level functions.
Do it like this
public partial class game : Form
{
int answer;
public game()
{
}
}
in your counter you can use a static counter or a page level variable also such as the variable answer
just reset the counter when the user have guessed correctly
I am tryig to fade-in a windows form using c# but it doesnt seem to work after I have shown the form. Is it possible to change the forms opacity after Ive shown it?
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Timers;
namespace ToolStrip
{
public partial class Form1 : Form
{
Form ToolForm = new ToolForm();
Form PropForm = new PropertyGrid();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ToolForm.FormBorderStyle = FormBorderStyle.FixedToolWindow;
ToolForm.Owner = this;
ToolForm.Show();
ToolForm.Location = new Point(50, 50);
}
private void button2_Click(object sender, EventArgs e)
{
PropForm.FormBorderStyle = FormBorderStyle.FixedToolWindow;
PropForm.Owner = this;
PropForm.Show();
PropForm.Location = new Point(50, 50);
System.Timers.Timer aTimer = new System.Timers.Timer(10000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
PropForm.Opacity = PropForm.Opacity - 0.25;
Console.WriteLine(PropForm.Opacity);
}
}
}
because you r using System.Timers.Timer which is a multithread timer, in it's OnTimedEvent() it calls control created by another thread, which cause exception.
If you use System.Windows.Forms.Timer, it will work. i tested.
Using your code (and creating the other necessary Form classes), I get a cross-threading exception the first time the timer fires and the event handler is called, as Benny suggests.
Making changes to your code to check InvokeRequired in the timer event handler, and use Invoke if necessary to change PropForm.Opacity, results in the opacity changing after the form is shown, as required.
Note that you probably want to start with an Opacity of 0, and increase it gradually - otherwise your form will start off completely solid and gradually fade out
I will mention in passing that Opacity will have no effect on some versions of Windows, though you say you have Opacity effects working elsewhere, so it shouldn't be that in this case.
Ive gotten it to work without timers:
int Loop = 0;
for (Loop = 100; Loop >= 5; Loop -= 10)
{
this.PropForm.Opacity = Loop / 95.0;
this.PropForm .Refresh();
System.Threading.Thread.Sleep(100);
}
but i cant seem to change this example to fade-in instead of out.