i add a loop to my program just to check something...(For verification)
for (int i = 1; i < total; i++){
for (int row = 0; row < 4; row++){
for (int col = 0; col < 4; col++){
pixel = block[i][row][col];
label1.Text = pixel.R.ToString("X");
System.Threading.Thread.Sleep(100);}}}
After Add this loop program works , but form doesnt show up. I Start Debuging and i saw that in this line it stops. Dont go any further.
Application.Run(new Form1());
Basicly begining of the program. So I isolate the System.Threading.Thread.Sleep(100);}}}
Part it is working now. Why this code is causing problem. I used the
using System.Threading.Tasks;.
Any idea or i can use other delay function... İ waiting for your help. Thank you..
You should never, ever, block the UI Thread (by means of sleeping or doing some heavy work) as the Thread can only either handle UI-Events (clicks, rerendering, resizing) or run your code, not both. In cases where you must execute some long running code from a event-handler, you can either start a new thread to do the work or run async code.
For you, something like this should work just fine:
public async void Form1_Load(object sender, EventArgs e) {
for (int i = 1; i < total; i++){
for (int row = 0; row < 4; row++){
for (int col = 0; col < 4; col++){
pixel = block[i][row][col];
label1.Text = pixel.R.ToString("X");
await Task.Delay();
}
}
}
}
While Sleep blocks the thread while it waits, await Task.Delay(); does not. It actually returns and lets the thread continue doing whatever it was doing previously and notifies the thread when it finished waiting so the thread can come back to your function later and continue running your code. (This is a simplification of how async and await works in C#)
Related
So! I am just playing around with progress bars in winForm but I noticed something. If I use a For statement the progress bar goes from 0 - 100 instant, even if I put a EX: Thread.Sleep(10000); It waits the time and then goes too 100%.
What am I doing wrong?
public void progressbar(object sender, EventArgs e)
{
for (int i = 0 ; i < 100; i++)
{
Thread.Sleep(10);
progressBar1.Value = i;
}
}
You're blocking the UI thread. While your event handler is running, your window can't handle any incoming window messages, so it will not update, and it will not repaint. Don't block the UI thread.
You need to update every interaction your progressbar. Note also that in your for, will go to 90 only and not to 100. Try this code:
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(10);
progressBar1.Value = i;
progressBar1.Refresh();
}
EDIT:
To work you must put in some event such as the click of a button , never in a Form Load
I am working on a user interface in C#. When user click the 'start' button, a huge 'for loop' starts to work. This process takes several minutes.
I want that just before forloop a message is displayed and after the forloop the message will disappear automaticly. My aim is to give an information message like 'Running, please wait' to the user.
Is there anyway to do that?
Here is the loop. It scans an image and makes some processes.
for (var i = 0; i <3504 ; i++)
for (var j = 0; j < 2306; j++)
{
........
}
You didn't say what GUI framework you're using, so I'm going to assume Forms. WPF would be similar though.
Let's assume the work begins when you click a button named "button1". Create a Form subclass that is your message (called, for the sake of example, "MessageWaitForm"). Then you can use it like this:
private void SomeWork()
{
for (var i = 0; i <3504 ; i++)
for (var j = 0; j < 2306; j++)
{
........
}
}
private void button1_Click(object sender, EventArgs e)
{
using (MessageWaitForm form = new MessageWaitForm())
{
form.Shown += async (sender1, e1) =>
{
await Task.Run(() => SomeWork());
form.Close();
}
form.ShowDialog();
}
}
This causes your processing to be executed in a separate asynchronous task, starting once the message dialog has been shown. When the task finishes, execution will return to the form.Close() statement, allowing the message form to be automatically closed.
Note that I had to make some assumptions and fill out your code example some just so that a usable answer could be provided. The above may not match your exact implementation as it stands now, but hopefully you can understand the basic concept being illustrated and conform it to your needs.
Perhaps your code would look something like this? I haven't had a chance to compile this but it should be enough to get you started.
private void StartBtn_OnClick(object sender, EventArgs e)
{
_isRunning = true;
CodeIsRunning.Visibility = Visibility.Visible;
//Anything else needed (disable buttons, etc)
Task.Factory.StartNew(() => {
for (var i = 0; i < 3504; i++)
for (var j = 0; j < 2306; j++)
{
...
}
_isRunning = false;
});
}
How can I run the code below in LinqPad as C# Program Thank you...
class ThreadTest
{
static void Main()
{
Thread t = new Thread (WriteY); // Kick off a new thread
t.Start(); // running WriteY()
// Simultaneously, do something on the main thread.
for (int i = 0; i < 1000; i++) Console.Write ("x");
}
static void WriteY()
{
for (int i = 0; i < 1000; i++) Console.Write ("y");
}
}
Result Expected
xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
So far I came up with
static void Main()
{
Thread t = new Thread (ThreadTest.WriteY); // Kick off a new thread
t.Start(); // running WriteY()
// Simultaneously, do something on the main thread.
for (int i = 0; i < 1000; i++) Console.Write ("x");
}
class ThreadTest
{
public static void WriteY()
{
for (int i = 0; i < 1000; i++) Console.Write ("y");
}
}
Actual Result
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...
As seen on Result Expected it should be mixed X and Y.
Unfortunately Actual Result is 1000 times X and 1000 times Y
UPDATE
This sample - along with all the others in the concurrency chapters of C# 5 in a Nutshell are downloadable as a LINQPad sample library. Go to LINQPad's samples TreeView and click 'Download/Import more samples' and choose the first listing. – Joe Albahari
Thread switching is by nature non-deterministic. I can run your program multiple times and get varying results.
If you want the switching to be more evident, add some pauses:
static void Main()
{
Thread t = new Thread (ThreadTest.WriteY); // Kick off a new thread
t.Start(); // running WriteY()
// Simultaneously, do something on the main thread.
for (int i = 0; i < 1000; i++)
{
Console.Write ("x");
Thread.Sleep(1);
}
}
class ThreadTest
{
public static void WriteY()
{
for (int i = 0; i < 1000; i++)
{
Console.Write ("y");
Thread.Sleep(1);
}
}
}
I cannot explain why this works, but changing to using Dump() seems to make it behave like the OP wants with the x's and y's "mixed" with every run (although with newlines between every output):
void Main()
{
Thread t = new Thread (ThreadTest.WriteY); // Kick off a new thread
t.Start(); // running WriteY()
// Simultaneously, do something on the main thread.
for (int i = 0; i < 1000; i++) "x".Dump();
}
class ThreadTest
{
public static void WriteY()
{
for (int i = 0; i < 1000; i++) "y".Dump();
}
}
From the LinqPAD documentation:
LINQPad's Dump command feeds the output into an XHTML stream which it
displays using an embedded web browser (you can see this by
right-clicking a query result and choosing 'View Source'. The
transformation into XHTML is done entirely using LINQ to XML, as one
big LINQ query! The deferred expansion of results works via
JavaScript, which means the XHTML is fully prepopulated after a query
finishes executing. The lambda window populates using a custom
expression tree visitor (simply calling ToString on an expression tree
is no good because it puts the entire output on one line).
I also know that LinqPAD overrides the default Console.WriteLine behavior, so perhaps that has something to do with it.
I am brand new to the idea of BackgroundWorkers, so this has me a little perplexed.
So I created a new WPF Application and created a BackgroundWorker and List class variable:
public partial class MainWindow : Window
{
private BackgroundWorker bw = new BackgroundWorker();
private List<int> tempList = new List<int>();
...
Then I use the BackgroundWorker to populate that list: (In the same class btw)
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Random r = new Random();
for (int j = 1; j <= 100; j++)
{
for (int i = 0; i < 1000; i++)
{
tempList.Add(r.Next(100));
}
...
}
}
Now here is the part that's getting me...
The code that populates that list seems to be working fine. When I step through its execution, *it behaves as I have intended until the exact moment the code exits the bw_DoWork method.* After that point, it reverts back to an empty list. I changed the list to static at one point but nothing changed.
So why is this List not persisting throughout the programs execution?
I am(was) almost certain that this is some issue with the list being allocated in different memory regions for each thread, but I simply know far too little about about BackgroundWorker and MultiThreading in general to diagnose it myself.
Any help would be appreciated.
Before you start using more expensive options such as locking or thread safe collections. Try out Threading Tasks. If they work then you have some kind of a problem with your BackgroundWorker, if they don't then your code touches the list somewhere and you'll have to trace that.. (I just think Tasks are so much easier to work with)
private void bw_DoWork()
{
Task.Factory.StartNew(
() =>
{
var r = new Random();
for (int j = 1; j <= 100; j++)
{
for (int i = 0; i < 1000; i++)
{
tempList.Add(r.Next(100));
}
//the rest of whaterver you're doing...
}
});
}
#Stephen Marsh like #Douglas said you need to wait until work is finish.
See this:
// this execute the DoWork asynchronously.
bw.RunWorkerAsync();
// asynchronously means the next line may be executed
// before the DoWork fill the list. In fact can be executed
// before the DoWork begin.
MessageBox.Show("Without wait: " + tempList.Count.ToString());
To correct you can add this line before call RunWorkerAsync:
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
and put this in any place of the MainWindows class.
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Completed: " + tempList.Count.ToString());
}
In my tests always the result was:
"Without wait: 0"
"Completed: 100000"
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Winforms Progress bar Does Not Update (C#)
First time asking a question here for me.
I'll try to explain my problem using this code snippet:
progressBar1.Maximum = 50;
for (int i = 0; i < 50; i++)
{
progressBar1.Value++;
}
MessageBox.Show("Finished");
progressBar1.Value = 0;
The problem with this code is that the MessageBox pops up at the time the for loop is finished, not when the progressbar has finished drawing. Is there any way to wait until the progressbar has finished drawing before continuing?
Thanks guys!
You might want to have a look at System.Windows.Forms.Application.DoEvents(). Reference
progressBar1.Maximum = 50;
for (int i = 0; i < 50; i++)
{
progressBar1.Value++;
Application.DoEvents();
}
MessageBox.Show("Finished");
progressBar1.Value = 0;
The issue here is that you are doing all of your work on the UI thread. In order to re-draw the UI, you would normally need to pump windows messages.The simplest way to fix this would be to tell the progress bar to update. Calling Control.Update will force any pending drawing to be completed synchronously.
progressBar1.Maximum = 50;
for (int i = 0; i < 50; i++)
{
progressBar1.Value++;
progressBar1.Update();
}
MessageBox.Show("Finished");
progressBar1.Value = 0;
The other methods that may work would be to use a background thread (with all of the extra Control.Invoke calls needed to synchronize back to the UI thread). DoEvents (as mentioned previously) should also work -- DoEvents will allow your window to process messages again for a time which may allow your paint messages through. However, it will pump all of the messages in the message queue so it may cause unwanted side effects.
Try the following code
progressBar1.Maximum = 50;
for (int i = 0; i < 50; i++)
{
this.SuspendLayout();
progressBar1.Value++;
this.ResumeLayout();
}
MessageBox.Show("Finished");
progressBar1.Value = 0;