I need to have a progress bar drain from full to empty in 5 seconds and i want to be able to interact with other parts of the form application as well. How do I make this happen?
I wrote this block where the program creates a new thread and iterates through it. Each iteration the thread drains a certain amount from it with 'timeToComplete' and finally waits a second.
private void CountDown()
{
int timeToComplete = 5; //Time in seconds
Thread thread = new Thread(() => {
while (progressBar1.Value >= 0)
{
progressBar1.Value -= progressBar1.Maximum / timeToComplete;
Thread.Sleep(1000); //Time is 1 second
}
});
thread.Start();
}
Related
So I am currently developing a C# Forms App, and in that Forms App I have a Backgroundworker that loops through a list with DataGridViewRow's, and creates a Thread for each Row. In that Thread, I sleep the program for as long as the user inputs, but I would like to update a string in that Thread while the Thread is sleeping, so basically prevent one function from sleeping inside the Thread itself. Is that possible?
I appreciate any help!
Here's an example of calling a task that says "Hello", then sleeps for 5 seconds, then says "Goodbye". But while it's sleeping, it starts another task that does a simple countdown.
Maybe this will be helpful to you:
private static void Main()
{
var sleepTime = TimeSpan.FromSeconds(5);
var sleepyTask = Task.Factory.StartNew(() =>
{
Console.WriteLine("I'm going to sleep");
// Before sleeping, launch a countdown timer
Task.Factory.StartNew(() =>
{
Countdown(sleepTime);
});
// Now go to sleep
Thread.Sleep(sleepTime);
Console.WriteLine("I'm back!");
});
sleepyTask.Wait();
GetKeyFromUser("\nDone! Press any key to exit...");
}
private static void Countdown(TimeSpan time)
{
var seconds = time.TotalSeconds;
// Write something once per second for 'seconds' seconds
while (seconds > 0)
{
Console.WriteLine(seconds--);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
I am trying to do something with a timer in a loop and after the timer finishes its work, app starts another turn in the loop. But because I don't know how to ask the main thread stop running while timer is running, the main thread goes to the next turn immediately.
I did something about lock.
This is the loop
for (int i = 0; i < step; i++)
{
Monitor.Enter(locker);
//start timer
}
then the code inside of the timer
t_tick = (senders, args) =>
{
if (condition)
{
//do something
}
else
{
//do something
Monitor.Exit(AirplaneManager.locker);
t.Stop();
}
};
t.Tick += t_tick;
t.Interval = 30;
t.Start();
But this gives me an exception while the code runs into the monitor in timer : Object synchronization method was called from an unsynchronized block of code.
Is there any solution? Or I can use other way to reach my goal?
Thanks!
If you want the current thread to block for a set timespan, you can just use Thread.Sleep(TimeSpan)
https://msdn.microsoft.com/en-us/library/274eh01d(v=vs.110).aspx
You don't need to use another thread.
I want to run a process every one minute, but I have been told that the Timer is working every x minute + the time required for the process to finish. but I want the thread to work every 1 minute even though the thread process may keep working for 1 hour.
I hope you got me, so in the final image, I may have 10 threads working together.
is that possible ?
Depends on the timer. Simple test shows that System.Threading.Timer works the way you want:
var timer = new Timer(s => { "Start".Dump(); Thread.Sleep(10000); "Hi!".Dump(); },
null, 1000, 1000);
Thread.Sleep(20000);
timer.Dump();
The callback executes every second even though it takes ten seconds to execute.
This is basically because the callback for this particular timer is simply posted to the threadpool, while e.g. System.Windows.Forms.Timer is actually tied to the UI thread. Of course, if you simply start a new thread (or queue work, or start a new task etc.) in the callback of winforms timer, it will work in a similar (albeit less precise) way.
Using the right tool for the job usually makes things much easier :)
Create a Timer and on the elapse event just fire a new thread to do the work, like the below example:
public class Example
{
private static Timer aTimer;
public static void Main()
{
// Create a timer with a two second interval.
aTimer = new Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program... ");
Console.ReadLine();
Console.WriteLine("Terminating the application...");
}
public static void DoWork()
{
var workCounter = 0;
while (workCounter < 100)
{
Console.WriteLine("Alpha.Beta is running in its own thread." + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
workCounter++;
}
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Create the thread object, passing in the method
// via a delegate.
var oThread = new Thread(DoWork);
// Start the thread
oThread.Start();
}
}
Since .NET 4.0 Tasks are preferred to Threads.
The overhead of Task management is minimal.
// Create a task spawning a working task every 1000 msec
var t = Task.Run(async delegate
{
while (isRunning)
{
await Task.Delay(1000);
Task.Run(() =>
{
//your work
};
}
});
i am programming a benchmark tool, that reads a bunch of variables from a local server in a thread.
int countReads = 1000;
Int64 count = 0;
for (int i = 0; i < countReads; i++)
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
DateTime start = DateTime.Now;
session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos);
DateTime stop = DateTime.Now;
Thread.CurrentThread.Priority = ThreadPriority.Normal;
TimeSpan delay = (stop - start);
double s = delay.TotalMilliseconds;
count += (Int64)s;
Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
{
progressBar1.Value = i;
}));
}
double avg = (double)count / countReads;
Dispatcher.Invoke(DispatcherPriority.Input, new Action(() =>
{
listBox1.Items.Add(avg);
}));
I am calculating the timespan it took to proceed the read and getting the average timespan at the end.
DateTime start = DateTime.Now;
session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos);
DateTime stop = DateTime.Now
if i run the code without updating the progressbar it took about 5ms average.
but if i run it with
Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
{
progressBar1.Value = i;
}));
it takes about 10 ms average.
My question is, why is the timespan higher when using the progressbar?
i am just calculating the timespan for the read. Not including the progressbar update.
Is there any way to evacuate the ui-painting so that it doesn´t effect my read-timespan?
Thanks for your help.
Best regards
Stop using Invoke to transfer progress information to the UI thread. Publish the progress information to a shared data structure or variable and have the UI thread poll for it using a timer on a reasonable interval. I know it seems like we have all been brainwashed into thinking Invoke is the be-all method for doing worker-to-UI thread interactions, but for simple progress information it can be (and often is) the worst method.
A polling method using a timer on the UI thread offers the following benefits.
It breaks the tight coupling that Invoke imposes on both the UI and worker threads.
The UI thread gets to dictate when and how often it should update the progress information instead of the other way around. When you stop and think about it this is how it should be anyway.
You get more throughput on both the UI and worker threads.
I know this does not directly answer your question as to why session.Read appears to run slower. Try changing your strategy for updating progress information from a push model (via Invoke) to a pull model (via a timer). See if that makes a difference. Even if it does not I would still stick with the pull model for the reasons listed above.
Here is what MSDN says about Dispatcher.Invoke
Executes the specified delegate synchronously on the thread the Dispatcher is associated with.
So, basically, Dispatcher.Invoke blocks until the dispatcher thread as handled the request.
Try Dispatcher.BeginInvoke instead.
If current executing thread is associated with Dispatcher you are using - Invoke() will block this thread so in this case try out using Dispatcher.BeginInvoke() it will do the job asynchronously.
MSDN, Dispatcher.Invoke Method:
Invoke is a synchronous operation; therefore, control will not return
to the calling object until after the callback returns.
BTW, just of interest try out DispatcherPriority.Send
I came 9 years late to the party, but I think this is an even easier solution: Just wait until the progress bar value reaches a certain threshold before updating it. In my example, I refresh the toolbar every fifth of the maximum value.
private static int progressBarMaxValue = -1;
private static int progressBarChunkSize = -1;
public static void progressBarSetNotRealTimeValue(ProgressBar progressBar, int argNewValue)
{
if (progressBarMaxValue != -1)
{
if (argNewValue < progressBarChunkSize)
{
//Threshold not reached yet, discard the new value.
return;
}
else
{
//Allow the update, and set the next threshold higher.
progressBarChunkSize += progressBarChunkSize;
}
}
if (Thread.CurrentThread.IsBackground)
{
progressBar.BeginInvoke(new Action(() =>
{
if (progressBarMaxValue == -1)
{
progressBarMaxValue = progressBar.Maximum;
progressBarChunkSize = progressBar.Maximum / 5;
}
progressBar.Value = argNewValue;
}));
}
else
{
progressBar.Value = argNewValue;
}
}
I am very inexperienced using multi-threading techniques, but here is what I have tried:
Thread thread = null;
for (int minute = 0; minute < 60; minute++)
{
Thread.Sleep(60000);
if (thread != null)
{
while (thread.ThreadState == ThreadState.Running) { }
}
thread = new Thread(delegate()
{
// Do stuff during the next minute whilst the main thread is sleeping.
});
thread.Start();
}
What I am trying to achieve here is to have a thread running and doing work whilst the main thread sleeps, but I am unsure why the above code doesn't work. What happens is that following the first loop (after starting the thread) the ThreadState doesn't seem to change from "Running". I am also curious as to whether there is a more elegant way of doing this.
Anyone know the problem?
Thread.Join is a better way to wait for a thread to end.
If you're using .Net 4, I'd recommend taking a look at the Task Class. It makes working with multithreading much easier/straight forward.
Using the Task class you can do this.
Task task = Task.Factory.StartNew(() =>
{
// Do stuff here.
});
task.Wait();
What you may be looking for is something more like this:
Thread thread = new Thread(delegate()
{
// Something that takes up to an hour
});
thread.Start();
for (int minute = 0; minute < 60; minute++)
{
Thread.Sleep(60000);
if (thread.IsAlive)
Console.WriteLine("Still going after {0} minute(s).", minute);
else
break; // Finished early!
}
// Check if it's still running
if (thread.IsAlive)
{
Console.WriteLine("Didn't finish after an hour, something may have screwed up!");
thread.Abort();
}
If this is what you're looking for, I'd take a look at the BackgroundWorker class.
Thread.Sleep(60000) is executed on the thread that calls it, in this case the main thread. Which is fine, but the "thread" doesn't know how long it has been running for and doesn't know when to actually stop. You need to have an object tell "thread" that it has been running for 60 seconds.
Thread thread = null;
for (int minute = 0; minute < 60; minute++)
{
if (thread != null)
{
while (thread.ThreadState == ThreadState.Running) { }
}
thread = new Thread(delegate()
{
try
{
// Do stuff during the next minute whilst the main thread is sleeping.
}
catch (ThreadAbortException ex)
{
}
});
thread.Start();
Thread.Sleep(60000);
thread.Abort();
}
This should achieve what you want but isn't really the most elegant way of stopping a thread. A thread should really be ended using callbacks.