Thread sleeping in a BackgroundWorker - c#

I wrote a simple app that adds 100000 lines of "Hello World" to a list using a BackgroundWorker.
Below is the code of the work that my backgroundworker is doing in a separate thread:
private void BgWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
int min = 0;
foreach (var hw in hwList)
{
//new ManualResetEvent(false).WaitOne(1);
Thread.Sleep(1);
int progress = Convert.ToInt32((Double)min / hwList.Count * 100);
min++;
bgWorker.ReportProgress(progress);
}
}
// Updating the progress
private void BgWorkerOnProgressChanged(object sender, ProgressChangedEventArgs progressChangedEventArgs)
{
ProgressBar.Value = progressChangedEventArgs.ProgressPercentage;
}
All is working fine, except that if I remove the Thread.Sleep(1) the BackgroundWorker doesn't report the progress anymore. (I suppose it needs some time). Suspending the thread for 1 ms actually makes the BackgroundWorker report the progress but it's very slow.
My question is, is there a way I can get rid of thread sleeping but at the same time making the BackgroundWorker report the progress correctly?
From my understanding, suspending the BackgroundWorker is inevitable, since the thread needs some time to perform the task, but I'm wondering if there's a workaround.

I had issues where i was reporting progress to often, furthermore there is no reason to report the same progress so many times waste of cpu cycles.
private void BgWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
int min = 0;
int oldProgress = 0;
foreach (var hw in hwList)
{
// new ManualResetEvent(false).WaitOne(1);
// Thread.Sleep(1);
int progress = Convert.ToInt32((Double)min / hwList.Count * 100);
min++;
// Only report progress when it changes
if(progress != oldProgress){
bgWorker.ReportProgress(progress);
oldProgress = progress;
}
}
}
// Updating the progress
private void BgWorkerOnProgressChanged(object sender, ProgressChangedEventArgs progressChangedEventArgs)
{
ProgressBar.Value = progressChangedEventArgs.ProgressPercentage;
}

Instead of BackgroundWorker, I developed a class named SxProgress with a very simple interface that you may use in the following way :
int DesiredLinesCount = 100000 ;
List<string> Lines=new List<string>() ;
object[] UserObjects = new object[] { Lines } ;
SxProgress.Execute("Building lines",DesiredLinesCount,true,false,
BuildLines_ExecInThread,UserObjects)) ;
private bool BuildLines_ExecInThread(int ItemIndex,object[] UserObjects)
{
// some sleep to slow down the process (demonstration purpose only)
// if (ItemIndex % 10 ==0) System.Threading.Thread.Sleep(1) ;
List<string> Lines= (List<String>)UserObjects[0] ;
Lines.Add("Hello world") ;
return true ;
}
The SxProgress code is in the last message of this link
Note also that the class provides the same easy interface for parallel process, creating as many threads as cores in the computer with transparent dispatch of the items to the different threads.

will this work for WPF?
Unfortunately no : The class encompasses a form (winforms) with progressbar, labels and stop button.
Possible solution : I never tried it.
It may work by adding to WPF project 2 references from the "Add reference" dialog form (in ".NET" tab),i.e. "System.Windows.forms" and "WindowsFormsIntegration".
Then, in source code, add "using System.Windows.Forms;"
and "using System.Windows.Forms.Integration;"

Related

Realtime update chart in background without GUI freezing

I developed a simple windows form application showing a realtime updated chart:
In the following code:
private void Start_Click(object sender, EventArgs e)
{
cpuThread = new Thread(new ThreadStart(this.ThreadUpdateChart));
cpuThread.IsBackground = true;
cpuThread.Start();
}
private void ThreadUpdateChart()
{
if (chart1.IsHandleCreated)
{
this.Invoke((MethodInvoker) delegate { UpdateChart();});
}
else
{
//......
}
Thread.Sleep(1000);
}
private void UpdateChart()
{
for (int i = 0; i < sampleSize; i++)
{
chart1.Series["Signal"].Points.AddXY(i, 100 * var.NextDouble());
chart1.Update();
//Thread.Sleep(500);
}
}
My problem is that when I press the start button the chart is update correctly, but this freeze my GUI till the end of the updated, I would like to update the chart without freezing other GUI functions, is it possible? Any solution?
To start of, the threading does nothing useful in your example, it just runs some code on a background thread, that immediately asks the main thread to update the chart. So get rid of it unless you are doing something computationally expensive not shown in the example.
You should also get better performance by doing all changes to your chart at once, avoiding expensive things like rendering until all changes have been made. So I would try something like this:
private void UpdateChart()
{
var series = chart1.Series["Signal"];
for (int i = 0; i < sampleSize; i++)
{
series.Points.AddXY(i, 100 * var.NextDouble());
}
chart1.Update();
}
If this does not help I would recommend doing some profiling to find out what is actually blocking the UI thread.

ProgressBar in WPF Slows Down

I have read any resource under the sun on how to implement a progress bar in wpf, that will actually reflect the actual progress of a thread.
Note - ** I am tied to .NET 4 only, due to corporate decisions, so any of the newer technics will not be at my disposal unfortunately.
This is what I have tried so far:
the method I run is LoadTable(). when run directly, it takes about 5 seconds to finish. when it's run in a BackgroundWorker it takes about 15 seconds (3 times longer than calling it directly):
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bg = (BackgroundWorker)sender;
for (int i = 0; i <= 100; i++)
{
// a method that takes time to exceute.
LoadTable();
bg.ReportProgress(i);
}
}
I also tried to run the method on its own thread and the BackgroundWorker that reports to the progress bar on another thread like so:
private void LoadTable_2()
{
task = Task.Factory.StartNew(new Action(() => LoadTable()));
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
LoadTable_2();
BackgroundWorker bg = (BackgroundWorker)sender;
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(i);
bg.ReportProgress(i);
}
}
But in this case, there is no connection between the two threads and there is no way of preventing the progress bar from running to 99, and waiting there until the other thread that executes the LoadTable method will finish. it doesn't report the actual progress of the method's execution.
My question is how do I use BackgroundWorker to actually report the progress without slowing the execution down? Thanks!
No wonder it's slower when you call LoadTable() a hundred times (!) in a loop. You should only call it once.
Your LoadTable() API apparently doesn't support reporting progress though. There is no way to report progress of a method that doesn't return the current progress.
You should consider showing an intermediate progress bar (set IsIndeterminate to true). This is the best you can do because you can't know the current progress of LoadTable() if it doesn't report it.

C# Progressbar filling while method is working

Im building a little app which has a long loading time.
I want to display this loading time in a progressbar to see how long i have to wait till the programm is loaded.
I hope you understand what i want..
I tried the backgroundworker already but dont understand how to use it, in every example they use in the DoWork Event a simple
for (int i = 0; i < 100; i++)
{
//method etc here
backgroundWorker.ReportProgress(i);
}
But in my eyes this is senseless for me because this only repeats my method...
Thank you in advance!
EDIT:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Aktie dataAktie = new Aktie(aktien_name);
for (int i = 0; i < 100; i++)
{
dataAktie.ReadFromDatabase();
dataAktie.FetchData();
backgroundWorker.ReportProgress(i);
}
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Controls that have to be filled
}
But this Controls dont get data im veryyyyy confused
The following code example demonstrates the use of the ReportProgress method to report the progress of an asynchronous operation to the user.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// This method will run on a thread other than the UI thread.
// Be sure not to manipulate any Windows Forms controls created
// on the UI thread from this method.
backgroundWorker.ReportProgress(0, "Working...");
Decimal lastlast = 0;
Decimal last = 1;
Decimal current;
if (requestedCount >= 1)
{ AppendNumber(0); }
if (requestedCount >= 2)
{ AppendNumber(1); }
for (int i = 2; i < requestedCount; ++i)
{
// Calculate the number.
checked { current = lastlast + last; }
// Introduce some delay to simulate a more complicated calculation.
System.Threading.Thread.Sleep(100);
AppendNumber(current);
backgroundWorker.ReportProgress((100 * i) / requestedCount, "Working...");
// Get ready for the next iteration.
lastlast = last;
last = current;
}
backgroundWorker.ReportProgress(100, "Complete!");
}
** http://msdn.microsoft.com/en-us/library/a3zbdb1t%28v=vs.110%29.aspx
A BackgroundWorker and it's ReportProgress method are no magic wanda that simply shows you any progress you want, you actually have to change your code to do so.
The DoWork event handler should contain the code you want to execute in the background. Ideally this is something for progress can be measured easily. For example if you have to process 10 items then after each item you could say I'm now 10% further done. That's why the example code contains a for loop.
Your code only contains two method calls, ReadFromDatabase and FetchData. So you could simply do
dataAktie.ReadFromDatabase();
backgroundWorker.ReportProgress(50); // 50% done
dataAktie.FetchData();
backgroundWorker.ReportProgress(100); // 100% done
Obviously that not really perfect. The only way to have more accurate progress is to change the ReadFromDatabase and FetchData methods, for example let them take the BackgroundWorker object as a parameter so that they can also report progress, or provide a callback for that.

How to use a BackgroundWorker to update multiple labels?

This is a follow up question to Updating a dialog from another form (The code and screenshots can be found there)
To solve my GUI hanging problem I received 2 recommendations:
Using Application.DoEvents()
Using a BackgroundWorker
The DoEvents() approach works, however it has been pointed out that I should not use it. Indeed, I notice that the GUI updates correctly but is unresponsive for short times.
That's why I want to use a BackgroundWorker and have read up on it.
I don't understand how I would implement it so that it can be used to update the 4 labels in my example code separately, though.
I want to show the progress (and update 4 dialog labels) as the program successfully finishes one job. The BackgroundWorker has only 1 DoWork() though. I have tried to use the e.Argument of the DoWorkEventArgs to differentiate between the different update methods but that attempt had failed.
public partial class BackgroundWorkerImportStatusDialog : Form
{
private BackgroundWorker dialogWorker = new BackgroundWorker();
private string path;
private string clientName;
public BackgroundWorkerImportStatusDialog()
{
InitializeComponent();
}
public void updateFileStatus(string path)
{
this.path = path;
dialogWorker = new BackgroundWorker();
dialogWorker.DoWork += new DoWorkEventHandler(updateLabels);
dialogWorker.RunWorkerAsync(UpdateComponent.FileStatus);
}
public void updatePrintStatus()
{
dialogWorker = new BackgroundWorker();
dialogWorker.DoWork += new DoWorkEventHandler(updateLabels);
dialogWorker.RunWorkerAsync(UpdateComponent.PrintStatus);
}
public void updateImportStatus(string clientName)
{
this.clientName = clientName;
dialogWorker = new BackgroundWorker();
dialogWorker.DoWork += new DoWorkEventHandler(updateLabels);
dialogWorker.RunWorkerAsync(UpdateComponent.ImportStatus);
}
public void updateArchiveStatus()
{
dialogWorker = new BackgroundWorker();
dialogWorker.DoWork += new DoWorkEventHandler(updateLabels);
dialogWorker.RunWorkerAsync(UpdateComponent.ArchiveStatus);
}
private void updateLabels(object sender, DoWorkEventArgs e)
{
MessageBox.Show(e.Argument.ToString());
if ((UpdateComponent) e.Argument == UpdateComponent.FileStatus)
{
t_filename.Text = path;
}
if ((UpdateComponent) e.Argument == UpdateComponent.PrintStatus)
{
t_printed.Text = "sent to printer";
}
if ((UpdateComponent) e.Argument == UpdateComponent.ImportStatus)
{
t_client.Text = clientName;
}
if ((UpdateComponent) e.Argument == UpdateComponent.ArchiveStatus)
{
t_archived.Text = "archived";
}
}
public enum UpdateComponent { FileStatus, PrintStatus, ImportStatus, ArchiveStatus}
And I can't imagine having 4 BackgroundWorkers for this pretty trivial dialog is the solution.
As I understand your question, you want to have your dialog form inform the user about 4 different aspects of your application running:
printing status
file status
import status
archiver status
Background worker could be used to periodically check each one. You may advanced progressbar by 25% after status of each operation is checked (and update your UI with appropriate information).
You may also try async programming - i.e. just start the operation, and lets your application continue. When the operation completes, your application will be notified, and could update information on the form.
Depending on the .NET framework you're using you may use async and await (avaialble since .NET 4.5 / C# 5 - async & await on MSDN) or classic approach to asynchronous programming.
Edit:
I am not sure that BackgroundWorker is the best solution in this situation. I can imagine having something like:
BackhgroundWorker checking things just once - i.e. check printing status once, file status once, import status once, archiver status once. This may sound silly, but it could be user behavior driver - i.e. explicitly launched when user clicks or invokes this mechanism any other way. ProgressBar could be put on the application's statausbar, so that user knows that 'application is actually doing something'.
Previous approach could be improved a bit - you never actually finish your job in BackgroundWorker - instead inside your main method you just have an infinite loop. This will allow you to check things periodically. In this approach there is no point in increasing the progress.
Sample for the second approach:
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
CheckPrintingStatus();
CheckFileStatus();
CheckImportStatus();
CheckArchiverStatus();
System.Threading.Thread.Sleep(5000); // sleep for 5 seconds
}
}
}
There is a question if this solution (second approach) is better than having a thread created explicitly. You could think of creating 4 different threads, so that each could check something else. This would be a bit heavier on the OS, but on the other hand you can set different sleep times for every operation.
If you go for bare threads - you may want to use ThreadPool instead of creating threads explicitly.

How do I run a simple bit of code in a new thread?

I have a bit of code that I need to run in a different thread than the GUI as it currently causes the form to freeze whilst the code runs (10 seconds or so).
Assume I have never created a new thread before; what's a simple/basic example of how to do this in C# and using .NET Framework 2.0 or later?
Good place to start reading is Joe Albahari.
If you want to create your own thread, this is as simple as it gets:
using System.Threading;
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
/* run your code here */
Console.WriteLine("Hello, world");
}).Start();
BackgroundWorker seems to be best choice for you.
Here is my minimal example. After you click on the button the background worker will begin working in background thread and also report its progress simultaneously. It will also report after the work completes.
using System.ComponentModel;
...
private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
// this allows our worker to report progress during work
bw.WorkerReportsProgress = true;
// what to do in the background thread
bw.DoWork += new DoWorkEventHandler(
delegate(object o, DoWorkEventArgs args)
{
BackgroundWorker b = o as BackgroundWorker;
// do some simple processing for 10 seconds
for (int i = 1; i <= 10; i++)
{
// report the progress in percent
b.ReportProgress(i * 10);
Thread.Sleep(1000);
}
});
// what to do when progress changed (update the progress bar for example)
bw.ProgressChanged += new ProgressChangedEventHandler(
delegate(object o, ProgressChangedEventArgs args)
{
label1.Text = string.Format("{0}% Completed", args.ProgressPercentage);
});
// what to do when worker completes its task (notify the user)
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
delegate(object o, RunWorkerCompletedEventArgs args)
{
label1.Text = "Finished!";
});
bw.RunWorkerAsync();
}
Note:
I put everything in single method
using C#'s anonymous method for
simplicity but you can always pull
them out to different methods.
It is safe to update GUI within
ProgressChanged or
RunWorkerCompleted handlers.
However, updating GUI from DoWork
will cause
InvalidOperationException.
The ThreadPool.QueueUserWorkItem is pretty ideal for something simple. The only caveat is accessing a control from the other thread.
System.Threading.ThreadPool.QueueUserWorkItem(delegate {
DoSomethingThatDoesntInvolveAControl();
}, null);
Here is another option:
Task.Run(()=>{
//Here is a new thread
});
Quick and dirty, but it will work:
Using at top:
using System.Threading;
simple code:
static void Main( string[] args )
{
Thread t = new Thread( NewThread );
t.Start();
}
static void NewThread()
{
//code goes here
}
I just threw this into a new console application for an exmaple
Try using the BackgroundWorker class. You give it delegates for what to run, and to be notified when work has finished. There is an example on the MSDN page that I linked to.
If you want to get a value:
var someValue;
Thread thread = new Thread(delegate()
{
//Do somthing and set your value
someValue = "Hello World";
});
thread.Start();
while (thread.IsAlive)
Application.DoEvents();
Put that code in a function (the code that can't be executed on the same thread as the GUI), and to trigger that code's execution put the following.
Thread myThread= new Thread(nameOfFunction);
workerThread.Start();
Calling the start function on the thread object will cause the execution of your function call in a new thread.
Here how can use threads with a progressBar , its just for understing how the threads works, in the form there are three progressBar and 4 button:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread t, t2, t3;
private void Form1_Load(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false;
t = new Thread(birinicBar); //evry thread workes with a new progressBar
t2 = new Thread(ikinciBar);
t3 = new Thread(ucuncuBar);
}
public void birinicBar() //to make progressBar work
{
for (int i = 0; i < 100; i++) {
progressBar1.Value++;
Thread.Sleep(100); // this progressBar gonna work faster
}
}
public void ikinciBar()
{
for (int i = 0; i < 100; i++)
{
progressBar2.Value++;
Thread.Sleep(200);
}
}
public void ucuncuBar()
{
for (int i = 0; i < 100; i++)
{
progressBar3.Value++;
Thread.Sleep(300);
}
}
private void button1_Click(object sender, EventArgs e) //that button to start the threads
{
t.Start();
t2.Start(); t3.Start();
}
private void button4_Click(object sender, EventArgs e)//that button to stup the threads with the progressBar
{
t.Suspend();
t2.Suspend();
t3.Suspend();
}
private void button2_Click(object sender, EventArgs e)// that is for contuniue after stuping
{
t.Resume();
t2.Resume();
t3.Resume();
}
private void button3_Click(object sender, EventArgs e) // finally with that button you can remove all of the threads
{
t.Abort();
t2.Abort();
t3.Abort();
}
}
If you are going to use the raw Thread object then you need to set IsBackground to true at a minimum and you should also set the Threading Apartment model (probably STA).
public static void DoWork()
{
// do some work
}
public static void StartWorker()
{
Thread worker = new Thread(DoWork);
worker.IsBackground = true;
worker.SetApartmentState(System.Threading.ApartmentState.STA);
worker.Start()
}
I would recommend the BackgroundWorker class if you need UI interaction.
// following declaration of delegate ,,,
public delegate long GetEnergyUsageDelegate(DateTime lastRunTime,
DateTime procDateTime);
// following inside of some client method
GetEnergyUsageDelegate nrgDel = GetEnergyUsage;
IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null);
while (!aR.IsCompleted) Thread.Sleep(500);
int usageCnt = nrgDel.EndInvoke(aR);
Charles your code(above) is not correct. You do not need to spin wait for completion. EndInvoke will block until the WaitHandle is signaled.
If you want to block until completion you simply need to
nrgDel.EndInvoke(nrgDel.BeginInvoke(lastRuntime,procDT,null,null));
or alternatively
ar.AsyncWaitHandle.WaitOne();
But what is the point of issuing anyc calls if you block? You might as well just use a synchronous call. A better bet would be to not block and pass in a lambda for cleanup:
nrgDel.BeginInvoke(lastRuntime,procDT,(ar)=> {ar.EndInvoke(ar);},null);
One thing to keep in mind is that you must call EndInvoke. A lot of people forget this and end up leaking the WaitHandle as most async implementations release the waithandle in EndInvoke.
another option, that uses delegates and the Thread Pool...
assuming 'GetEnergyUsage' is a method that takes a DateTime and another DateTime as input arguments, and returns an Int...
// following declaration of delegate ,,,
public delegate long GetEnergyUsageDelegate(DateTime lastRunTime,
DateTime procDateTime);
// following inside of some client method
GetEnergyUsageDelegate nrgDel = GetEnergyUsage;
IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null);
while (!aR.IsCompleted) Thread.Sleep(500);
int usageCnt = nrgDel.EndInvoke(aR);
There are many ways of running separate threads in .Net, each has different behaviors. Do you need to continue running the thread after the GUI quits? Do you need to pass information between the thread and GUI? Does the thread need to update the GUI? Should the thread do one task then quit, or should it continue running? The answers to these questions will tell you which method to use.
There is a good async method article at the Code Project web site that describes the various methods and provides sample code.
Note this article was written before the async/await pattern and Task Parallel Library were introduced into .NET.
How to: Use a Background Thread to Search for Files
You have to be very carefull with access from other threads to GUI specific stuff (it is common for many GUI toolkits). If you want to update something in GUI from processing thread check this answer that I think is useful for WinForms. For WPF see this (it shows how to touch component in UpdateProgress() method so it will work from other threads, but actually I don't like it is not doing CheckAccess() before doing BeginInvoke through Dispathcer, see and search for CheckAccess in it)
Was looking .NET specific book on threading and found this one (free downloadable). See http://www.albahari.com/threading/ for more details about it.
I believe you will find what you need to launch execution as new thread in first 20 pages and it has many more (not sure about GUI specific snippets I mean strictly specific to threading). Would be glad to hear what community thinks about this work 'cause I'm reading this one. For now looked pretty neat for me (for showing .NET specific methods and types for threading). Also it covers .NET 2.0 (and not ancient 1.1) what I really appreciate.
I'd recommend looking at Jeff Richter's Power Threading Library and specifically the IAsyncEnumerator. Take a look at the video on Charlie Calvert's blog where Richter goes over it for a good overview.
Don't be put off by the name because it makes asynchronous programming tasks easier to code.

Categories

Resources