It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have a function that i want to run it every 1 second and beside that i do have other stuff ,
because im using Thread on my other function and avoiding Window Crashes i decided to use Backgroundworker to call the function that suppose to run like this:
Main()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
}
public void worker_DoWork(object sender, EventArgs e)
{
AutoChecking(); // thats a function should Run on Background every 1 second
}
public void AutoChecking()
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
if (SystemisGood == true)
Updatecolor.Fill = Green;
else
Updatecolor.Fill = Red;
}));
}
However this function only works one time now any reason or solution to make it work every one second and Stay with backgroundworker ?!
P.S: i dont want to use Timer...
It is wasteful to not use a timer, since those are very lightweight and just send a periodic message, but you could accomplish what you want by using a low overhead polling loop and checking the time, much as what is done by the timer code itself. For example:
Main()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
}
bool exitBGThread = false;
public void worker_DoWork(object sender, EventArgs e)
{
TimeSpan interval = new TimeSpan(0, 0, 1);
while (!exitBGThread)
{
DateTime start = DateTime.Now;
AutoChecking(); // thats a function should Run on Background every 1 second
while (!exitBGThread)
{
DateTime cur = DateTime.Now;
if (cur - start >= interval)
break;
Thread.Sleep(100);
}
}
}
public void AutoChecking()
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
if (SystemisGood == true )
Updatecolor.Fill = Green;
else
Updatecolor.Fill = Red;
}));
}
This is a bit simplified as you would want to use lock { } if you actually used exitBGThread, but you get the idea.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
So I've been reading a lot of articles that have been discouraging the use of Application.DoEvents() and even saying that it should never be used but I can't seem to find a good alternative for my scenario...
The application that I am working on has a method that is called by a this.Shown event when the main GUI form first launches. The method does some work that takes about a minute of time so the same method also creates a form that is essentially a custom made progress bar. Keep in mind that this process is currently single threaded so when this method is doing work the main GUI and and progress bar become non-responsive. If the user clicks anywhere during this time, the screens go blank. So I'm working on putting some of the work that this method does in a BackgroundWorker thread. Here is what I've come up with:
private BackgroundWorker Bgw = new BackgroundWorker();
private int LoadPercentage = 0;
//this sub is executed on the main UI thread
public void RunBgw()
{
bool StopThread = false;
//this object should be created in this method and needs to be updated as the child thread is doing work
MyCustomDialog dialog = new MyCustomDialog();
dialog.UpdateProgress(0, "My message");
dialog.Show();
this.Invalidate();
this.Refresh();
//critical properties to set if you want to report progress/be able to cancel the operation
Bgw.WorkerSupportsCancellation = true;
Bgw.WorkerReportsProgress = true;
//add handlers to Bgw so events will fire
Bgw.DoWork += new DoWorkEventHandler(Bgw_DoWork);
Bgw.ProgressChanged += new ProgressChangedEventHandler(Bgw_ProgressChanged);
Bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bgw_RunWorkerCompleted);
//fire off thread
Bgw.RunWorkerAsync();
while (Bgw.IsBusy == true)
{
if (BW.CancellationPending == true)
{
StopThread = true;
break;
}
Application.DoEvents();
if(LoadPercentage == 10)
{
dialog.UpdateProgress(LoadPercentage, "Still working...");
this.Invalidate();
this.Refresh();
}
if(LoadPercentage == 50)
{
dialog.UpdateProgress(LoadPercentage, "Halfway done...");
this.Invalidate();
this.Refresh();
}
// etc...
//slow down loop so it doesnt take up all the CPU
Thread.Sleep(200);
}
if(!StopThread) {
//continue with something else.
}
}
private void Bgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker BgwLocal = sender as BackgroundWorker;
if ((BgwLocal.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
TimeConsumingWork();
BgwLocal.ReportProgress(10); //report progress back to the main UI thread
TimeConsumingWork();
BgwLocal.ReportProgress(15, SomeGuiIcon); //pass back specific gui icon
TimeConsumingWork();
BgwLocal.ReportProgress(50);
// etc...
}
}
private void Bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
LoadPercentage = e.ProgressPercentage; //set current percentage of progress
if(LoadPercentage == 15)
{
GuiIcon1 = (Icon)e.UserState; //set gui icon
}
}
private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
//error handling
}
else if (!(e.Error == null))
{
//error handling
}
else
{
//success
}
}
Everything is working well except that error handling has proven to be difficult and messy. Is there a better way of threading work while updating an existing object in the main thread??
Thanks for reading.
You should not be blocking the UI thread with this code:
while (Bgw.IsBusy == true) { ... }
Instead, allow RunBgw() to return to the caller. Use the events present on the BackgroundWorker to know when it has completed. Specifically
Bgw.ProgressChanged += new ProgressChangedEventHandler(Bgw_ProgressChanged);
reports on progress by calling
Bgw_ProgressChanged
and
Bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bgw_RunWorkerCompleted);
causes
Bgw_RunWorkerCompleted
to be invoked when the BackgroundWorker is done.
Update the progress bar from within Bgw_ProgressChanged.
Windows UI's are event driven. Your code is not making use of events to control program execution.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I want my ProgressBar starting in some point in my code and run total of seconds until my file finish, and of course I know how long the run of my file will take.
I try to read on MSDN but I did not understood how to use it.
My application run files (wireshark file, send the packet using bittwist) and each file will run few seconds and I want the option to see the progress ongoing.
For example I want to set my ProgressBar running for 30 seconds.
How can I do it?
Maybe you want something like this:
public void AnimateProgBar (int milliSeconds)
{
if (!timer1.Enabled) {
progressBar1.Value = 0;
timer1.Interval = milliSeconds / 100;
timer1.Enabled = true;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (progressBar1.Value < 100) {
progressBar1.Value += 1;
progressBar1.Refresh();
} else {
timer1.Enabled = false;
}
}
Then you just have to call AnimateProgBar(2000) to have your ProgressBar animated during 2 seconds.
EDIT: Sorry, I posted code in VB.NET. Modified to C#.
EDIT: You can add the handler and call the function in this way (for example):
private void Form1_Load(object sender, EventArgs e)
{
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
AnimateProgBar(2000);
}
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Deleted post and have code:
namespace StackOverflowQuestion
{
class Program
{
static void Main (string[] args)
{
var cw = new ConsoleWriter ();
for (int i = 0; i <= 5000000; i++)
{
cw.Write (i);
}
Console.ReadKey ();
}
}
class ConsoleWriter
{
private Stopwatch sw = new Stopwatch ();
public ConsoleWriter ()
{
sw.Start ();
}
public void Write (int pNumber)
{
if (sw.ElapsedMilliseconds >= 50)
{
Console.WriteLine (pNumber);
sw.Restart ();
}
}
}
}
And the output:
305940
651171
1002965
1358665
1715740
2069602
2419054
2772833
3127880
3485054
3844335
4204016
4557912
4913494
So everything works fine. In this example ConsoleWriter display number on console, but it could be displayed in Control surface. Like you see, even if I call 5000000 times Write method, it only updates UI after minimum 50 ms. Great, but notice in many cases the last value 5000000 will not be displayed. How to fix it? Should I use a class (thread) which will call event each 50 ms and it will check the value to write is changed?
You could use a timer
Timer _timer;
public void StartTimer()
{
_timer = new Timer();
_timer.Interval = 100; // 100 ms = 0.1 s
_timer.Tick += new EventHandler(timer_Tick);
_timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
myControl.Number = i;
}
In the control there should be something like
private int _number;
public int Number
{
get { return _number; }
set
{
if (value != _number) {
_number = value;
Invalidate();
}
}
}
The call of Invalidate() will trigger the Paint event. Your painting logic should be in the OnPaint method:
protected override void OnPaint(PaintEventArgs e)
{
... paint here
}
But of cause the for loop itself will freeze the application. You could use a second timer that updates the counter at a faster intervall than your display counter. Every code running on the UI-tread (main thread if you prefer) will freeze you UI until it terminates. An easy way of doing a heavy work in the background in a separate thread is to use the BackgroundWorker. The background worker automatically switches between UI-thread and worker-thread and allows you to report progess to the UI-thread.
You can also start a thread manually in order to update the counter. If this will be the only thread changing the number, no synchronisation mechanisms will be required. But never access the UI (a form or a control) from another thread than the UI-thread.
Here is a complete non-blocking solution using another thread for the counting
Timer _timer;
int _counter;
System.Threading.Thread _worker;
public frmTimerCounter()
{
InitializeComponent();
_worker = new System.Threading.Thread(() =>
{
while (_counter < 10000000) {
_counter++;
System.Threading.Thread.Sleep(20);
}
});
_worker.Start();
StartTimer();
}
public void StartTimer()
{
_timer = new System.Windows.Forms.Timer();
_timer.Interval = 100; // 100 ms = 0.1 s
_timer.Tick += new EventHandler(timer_Tick);
_timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
// I used a Label for the test. Replace it by your control.
label1.Text = _counter.ToString();
}
You didn't post any code but I can guess at what it looks like. You are doing way too much work in the property setter. This for() loop should never take more than a millisecond, way too short to ever notice a GUI freeze.
You get this by following the standard way controls repaint themselves. Which is lazily. You get that by calling the Invalidate() method. Like this:
class MyControl : Control {
private int number;
public int Number {
get { return this.number; }
set {
if (value != this.number) this.Invalidate();
this.number = value;
}
}
protected override void OnPaint(PaintEventArgs e) {
// TODO: paint number
//...
base.OnPaint(e);
}
}
You'll now also discover something else, there's no point to using that for() loop anymore. There never was one in the first place, a human being cannot possibly see the incredible rate at which a modern processor can increment a number. So you'll now replace that with:
myControl.Number = 50000;
If you actually meant for a human eye to see the number increasing then you are going to have to do it a lot slower. No more than about once every 50 millisecond, about the point where the changes turn into a blur. That requires a Timer.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I'm learning threads in C# so my first program will be 2 images that will be moving. But the problem is that I get an error when I try to do a new point in a thread:
Here's my code:
namespace TADP___11___EjercicioHilosDatos
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int x = 0;
int y = 0;
private void Form1_Load(object sender, EventArgs e)
{
Thread Proceso1 = new Thread(new ThreadStart(Hilo1));
Proceso1.Start();
}
public void Hilo1()
{
while (true)
{
x = pictureBox1.Location.X - 1;
y = pictureBox1.Location.Y;
pictureBox1.Location = new Point(x, y);
}
}
}
}
You can only update a control from the thread that control was created on. Controls do have an Invoke method that you can call from another thread. This method takes a delegate that specifies the work you would like to do on the control's thread:
var updateAction = new Action(() => { pictureBox1.Location = new Point(x,y); });
pictureBox1.Invoke(updateAction);
You have to Invoke it. For [obvious] reasons, you can't access controls created by a different thread so you have to use a delegate. Several similar SO questions:
How to update the GUI from another thread in C#? (111 upvotes)
Writing to a textBox using two threads
How to update textbox on GUI from another thread in C#
Writing to a TextBox from another thread?
If you check out the first link, Ian's great answer will demonstrate how you should do this in .Net 2.0 and 3.0. Or you can scroll down to the next answer, Marc's, which will show you how to do it in the simplest way.
Code:
//worker thread
Point newPoint = new Point(someX, someY);
this.Invoke((MethodInvoker)delegate {
pictureBox1.Location = newPoint;
// runs on UI thread
});
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Currently I have a background thread whose doWork calls a function similar to below.
private void ThreadForAnalyzingReqFile_DoWork(object sender, DoWorkEventArgs e)
{
AnotherClass.AVeryLongTimedFunction();
}
Now, the code shall wait until AVeryLongTimedFunction() in AnotherClass finishes (that may take about 1-2 minutes) While this happens, how do I know exactly what's happening? Is there any way I can be notified that function (in another class) finishes?
This thread is in my MainWindow class of WPF. I am using Visual Studio 2010.
There are many ways to do this. Two easy options:
(1) Create an event in your UI class such as UpdateProgress, and notify that event at meaningful intervals
Example:
private void ThreadForAnalyzingReqFile_DoWork(object sender, DoWorkEventArgs e)
{
AnotherClass processor = new AnotherClass();
processor.ProgressUpdate += new AnotherClass.ReallyLongProcessProgressHandler(this.Processor_ProgressUpdate);
processor.AVeryLongTimedFunction();
}
private void Processor_ProgressUpdate(double percentComplete)
{
this.progressBar1.Invoke(new Action(delegate()
{
this.progressBar1.Value = (int)(100d*percentComplete); // Do all the ui thread updates here
}));
}
And in "AnotherClass"
public partial class AnotherClass
{
public delegate void ReallyLongProcessProgressHandler(double percentComplete);
public event ReallyLongProcessProgressHandler ProgressUpdate;
private void UpdateProgress(double percent)
{
if (this.ProgressUpdate != null)
{
this.ProgressUpdate(percent);
}
}
public void AVeryLongTimedFunction()
{
//Do something AWESOME
List<Item> items = GetItemsToProcessFromSomewhere();
for (int i = 0; i < items.Count; i++)
{
if (i % 50)
{
this.UpdateProgress(((double)i) / ((double)items.Count)
}
//Process item
}
}
}
(2) Create a progress percentage field on AnotherClass. Occasionally interrogate this in your UI on a timer.
Try to pass a callback function to your "VeryLongTimedFunction" and call that every time some kind of "progress" event happens, like each time 50 items are processed, or 20 iterations are made , or whatever is the case with your operation.
As others hinted, there are multiple ways of achieving that, however the simplest seems to be just to use BackgroundWorker instead of a thread.
To indicate progress, simply set WorkerSupportsCancellation property to true and then invoke worker.ReportProgress(percentage complete) to indicate progress. For a completion notification use event notification, e.g.
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(method_run_on_complete);
private void method_run_on_complete(object sender, DoWorkEventArgs e) { ... }
For more details see:
http://www.dreamincode.net/forums/topic/112547-using-the-backgroundworker-in-c%23/
http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/28774446-144d-4716-bd1c-46f4bb26e016