I'm using Parallel.ForEach for the first time, where I'm processing files; in the context of a WinForms app.
As per guidance from other threads on this coding problem (Parallel.ForEach progress reporting) I have a public (int) counter property on my class which contains the parallel code, and it's successfully updating; I also have a Timer on my Form that periodically reads the counter.
The issue is that when I execute the parallel code the visible progress updating appears to stop, and then starts as soon as the parallel code is complete.
FYI - I'm calling the parallel code directly - that is, not through a background worker or async method.
Parallel.ForEach actually evaluates the query in parallel fashion but does wait for finishing of execution and blocks the calling thread.
You should use it on a separate thread/backgroundworker/task to get your progress variable updating while not blocking the UI.
If you are calling Parallel.ForEach() from your UI thread (lacking a code example, there's no way for us to know for sure what's happening), then the fact that that method stops and waits for all the processing to complete will prevent your UI thread from doing any other work, including a) allowing the timer event from being processed, and b) allowing the UI to be updated even if the timer even were processed.
One possible approach would be to wrap the call of Parallel.ForEach() in a call to Task.Run(). For example:
private async void button1_Click(object sender, EventArgs e)
{
// some stuff
await Task.Run(() => Parallel.ForEach(...));
// some other stuff
}
Alternatively, you could just execute the whole thing as individual tasks:
private async void button1_Click(object sender, EventArgs e)
{
// some stuff
List<Task> tasks = new List<Task>();
foreach (...)
{
tasks.Add(Task.Run(() => ...));
}
await Task.WhenAll(tasks);
// some other stuff
}
(The above examples leave out specifics, since without a code example in the question there's no way to know what would actually go there).
Either approach should free up your UI thread to handle the progress updating while the processing goes on.
Related
I have a function which I need to run in background because it freezes the UI until it completes. I tried to use Async/Await which lets me use the UI no matter the function completes running or not, but I noticed it is much slower. Why using async/await to a function takes longer time then calling that same function directly ? Is there any other alternative ?
private void btnClick(object sender, EventArgs e)
{
Math4OfficeRibbon.CallFunction();
MessageBox.Show("Task Finished");
}
public async void CallFunction()
{
await Task.Run(() => AwaitedFunction());
}
public static void AwaitedFunction()
{
// Do Something
// Takes longer time this way
}
In order to find out why it's much slower you can track events down in visual studio by using Console.WriteLine($"{event name} {DateTime.Now}")
And then seeing where it takes the most time in output window.
However about the alternatives, I suggest you use BackgroundWorker to run your tasks.
note that you need to invoke controls in order to make changes to the ui through the backgroundWorker
BackgroundWorker _worker = new BackgroundWorker();
_worker.DoWork+=(o,args)=>
{
//your code here.
}
_worker.RunWorkerAsync();
You also have RunWorkerCompleted event which you can use to do things after your task is done running.
Backgroundworker also has the IsBusy property which you can use along with a while loop to keep the thread waiting for its completion without freezing the UI by doing :
While(_worker.IsBusy)
{
Application.DoEvents();
}
In order to invoke to do things on the ui thread you need to do the following within BackgroundWorker:
BeginInvoke(new Action(()=>
{
//ui action here for example:
MessageBox.show("test")
}));
However in order to find out why your asynchronous operation takes alot of time you have to trace it using the console because you have all the code and you know what you're doing.
I have a method that utilises SendKeys.Send, waits for a few seconds using System.Threading.Thread.Sleep and then runs another method to check the colour of a pixel to see if it has changed. The method then runs again as it is called recursively.
This method needs to be able to run thousands of times before stopping. The Winform's UI seems to stop responding when this is running.
I tried to implement a background worker to take the strain off of the UI. I moved the recursive method's code over to the Do_Work event and called it with RunWorkerAsync but it crashed, reporting the following:
An exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll but was not handled in user code
Additional information: SendKeys cannot run inside this application because the application is not handling Windows messages.
What's the best way of moving the code away from the UI? I'm not very familiar with background workers so I may be doing it wrong.
Sounds like a case for async. Try replacing Thread.Sleep() with Task.Delay().
async void Button_Click(object sender, RoutedEventArgs e)
{
await SendMyKeysAsync();
}
async Task SendMyKeysAsync()
{
while (thePixelIsStillRed)
{
SendKeys.Send("whatever");
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
This approach leaves the UI thread free to continue pumping messages during the delay period, without spawning any additional threads.
Rather than a synchronous recursive method, you should write an asynchronous iterative method.
private async void Foo()
{
while(ShouldKeepLooping())
{
SendKeys.Send(keyToSend);
await Task.Delay(timespan.FromSeconds(2));
}
}
Making the method recursive adds nothing; making it iterative removes stack pressure. By making the method asynchronous, rather than synchronous, you don't block the UI thread.
I started off trying to add a progress bar to the windows form that updates the progress of code running within a Parallel.Foreach loop. In order to do this the UI thread has to be available to update the progress bar. I used a Task to run the Parallel.Foreach loop to allow the UI thread to update the progress bar.
The work done within the Parallel.Foreach loop is rather intensive. After running the executables of the program(not debugging within visual studio) with the Task, the program became unresponsive. This is not the case if I run my program without Task. The key difference I noticed between the two instances is that the program takes ~80% of the cpu when ran without Task, and ~5% when ran with Task.
private void btnGenerate_Click(object sender, EventArgs e)
{
var list = GenerateList();
int value = 0;
var progressLock = new object ();
progressBar1.Maximum = list.Count();
Task t = new Task(() => Parallel.ForEach (list, item =>
{
DoWork ();
lock (progressLock)
{
value += 1;
}
}));
t.Start();
while (!t.IsCompleted)
{
progressBar1.Value = value;
Thread.Sleep (100);
}
}
Side Note: I know that
Interlocked.Increment(ref int___);
works in place of the lock. Is it considered more efficient?
My Question is three fold:
1.) Why would the program with the Task become unresponsive when the load is much less?
2.) Does using Task to run Parallel.Foreach limit the thread pool of the Parallel.Foreach to only the thread running the task?
3.) Is there a way to make the UI thread responsive instead of sleeping for the .1 second duration without using cancellation token?
I'm grateful for any help or ideas, I've spent quite a lot of time researching this. I also apologize if I've violated any posting format or rules. I tried to adhere to them, but may have missed something.
You can greatly simplify your code there by using the built in Invoke method that invokes a delegate on the owning Windows synchronization context.
From MSDN:
Executes the specified delegate on the thread that owns the control's underlying window handle.
The Invoke method searches up the control's parent chain until it finds a control or form that has a window handle if the current control's underlying window handle does not exist yet.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string[] GenerateList() => new string[500];
void DoWork()
{
Thread.Sleep(50);
}
private void button1_Click(object sender, EventArgs e)
{
var list = GenerateList();
progressBar1.Maximum = list.Length;
Task.Run(() => Parallel.ForEach(list, item =>
{
DoWork();
// Update the progress bar on the Synchronization Context that owns this Form.
this.Invoke(new Action(() => this.progressBar1.Value++));
}));
}
}
This will invoke the Action delegate on the same UI thread that the Form belongs to, from within the Task.
Now to try and answer your questions
1.) Why would the program with the Task become unresponsive when the load is much less?
I'm not 100% sure, but this could be related to you locking a member on the UI thread. If the load is less, then the lock will happen more frequently, potentially causing the UI thread to "hang" while the progressbar is incremented.
You are also running a while loop that is sleeping the UI thread every 100 milliseconds. You'll see UI hanging due to that while loop.
2.) Does using Task to run Parallel.Foreach limit the thread pool of the Parallel.Foreach to only the thread running the task?
It does not. Several tasks will get created within the Parallel.ForEach call. The underlying ForEach uses a partitioner to spread the work out, and not create more tasks than what is necessary. It creates tasks in batches, and processes the batches.
3.) Is there a way to make the UI thread responsive instead of sleeping for the .1 second duration without using cancellation token?
I was able to handle that by removing the while loop and using the Invoke method to just go ahead and execute a lambda on the UI thread directly.
I would please like to know where I can get an example of multithreading or asynchronous threading.
In the application that I am busy with I have to run a thread in the background of my application to fetch a value that is changing. And whenever this value reaches a certain amount then it needs to call another function. All this has to run in the background of the program so that the user can still do something else on the application.
Any examples or links that could help would really be appreciated.
In order to summarize the options, I will try to list them here (maybe it would be a good idea to make this a community wiki).
First of all, you can simply start a function in another thread:
Thread t = new Thread( ThreadProc );
t.Start();
// now you can wait for thread to finish with t.Join() or just continue
// Thread.IsBackground allows to control how thread lifetime influences
// the lifetime of the application
...
static void ThreadProc() {...} // can also be non-static, but for simplicity....
Then you can use BackgroundWorker:
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += MyFunction;
bgWorker.RunWorkerAsync();
voud MyFunction(object o, DoWorkEventArgs args) {...}
You can use ProgressChanged and RunWorkerCompleted events for more control (as well as WorkerReportsProgress and other properties)
Another option is to use ThreadPool, if your method will not take too much time:
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
...
static void ThreadProc(Object stateInfo) { ... }
Yet another option is to call BeginInvoke on a delegate:
public delegate int MyDelegate(...);
MyDelegate del = SomeFunction;
IAsyncResult ar = del.BeginInvoke(...);
int result = del.EndInvoke(ar);
This will execute on a thread from the thread pool. If you need to wait on calling thread, you can use IAsyncResult.IsCompleted, but it will block the calling thread.
And of course, you can use Task:
var task = Task.Factory.StartNew(() => MyMethod());
This will also execute MyMethod on a thread from the thread pool, so the same warnings apply (although you can use TaskCreationOptions.LongRunning to ensure that the new thread is always created). Under some circumstances (when you wait on task) it can even execute on the same thread, but it is well optimized so you should not worry about that.
This is probably the option with best tradeoff of simplicity vs control (of course, there is no really 'the best'). Here are the benefits (shamelessly stolen from Jon Skeet's answer):
Adding continuations (Task.ContinueWith)
Waiting for multiple tasks to complete (either all or any)
Capturing errors in the task and interrogating them later
Capturing cancellation (and allowing you to specify cancellation to start with)
Potentially having a return value
Using await in C# 5
Better control over scheduling (if it's going to be long-running, say so when you create the task so the task scheduler can take that into account)
Well depending on the level of control that you seek a BackgroundWorker could easily work and its found within the System.ComponentModel.BackgroundWorker. Now here is a link to the MSDN docs on the subject matter : http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
a Simple usecase secenario is like so:
BackgrouWorker BG = new BackgroudWorker();
GB.DoWork += YourFunctionDelegate(object Sender, EventArgs e);
GB.RunWorkerAsync();
Now YourFunctionDelegate(object Sender,EventArgs e) should be what ever it is you want run in the background. However needs to follow this argument form, There are also a good amount of helper functions associated with the backgroundworker like onProgressChanged event that allows monitoring of obviously progress, which if you are new to threading can prove to be a pain at first if you try to make your own threads.
If you would like more control over execution and how the threads function you should take a look at the Task-Parallel-Library here: http://msdn.microsoft.com/en-us/library/dd460717.aspx Which has copious amount of information about multi-threading.
Also here is a great tutorial on how to create a C# thread: http://support.microsoft.com/default.aspx?scid=kb;en-us;815804
For an overview of asynchronous programming on Windows 8 in .Net 4.5:
http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx
For .Net 4.0 and older you can use the ThreadPool
System.Threading.ThreadPool.QueueUserWorkItem(obj =>
{
// Do some work
for (int i = 0; i < 1000; i++)
Math.Sin(i);
// Get back to the UI thread
App.Current.MainWindow.Dispatcher.BeginInvoke(
new Action(delegate
{
block.Text = "Done!";
}));
});
I have a blog post that compares and contrasts various implementations of background tasks, with advantages and disadvantages for each. Spoiler: Task is definitely the best option. Also, I recommend Task.Run over TaskFactory.StartNew.
If your background operation is truly asynchronous, then you may not need any background threading at all. LINQPad has a set of async examples that are a great starting point. These are more up-to-date than the chapter on threading (by the same author) that others have recommended.
When i use invoke inside AddListBoxItem function as seen below software become unreponsive and frozen but if i use BeginInvoke it works. Why is that happening ?
visual studio 2010 , C# 4.0
private void button2_Click(object sender, EventArgs e)
{
var watch = Stopwatch.StartNew();
Parallel.For(2, 20, (i) =>
{
var result = SumRootN(i);
AddListBoxItem("root " + i + " : " + result);
});
AddListBoxItem(watch.ElapsedMilliseconds.ToString());
}
private delegate void AddListBoxItemDelegate(object item);
private void AddListBoxItem(object item)
{
if (this.listBox1.InvokeRequired)
{
this.listBox1.Invoke(new AddListBoxItemDelegate(this.AddListBoxItem), item);
}
else
{
this.listBox1.Items.Add(item);
}
}
Your UI thread will wait for Parallel.For to complete before it continues. That means it can't process any further UI messages until it's completed.
Now when the worker threads call Invoke, they wait until the UI thread processes the delegate before they continue. So they're waiting for the UI thread to get free, basically.
Hence, you have a deadlock - the UI thread is waiting for the tasks, which are waiting for the UI thread... BeginInvoke works because then the task threads don't wait for the delegates to be processed in the UI thread.
I would suggest that you don't call Parallel.For in the UI thread to start with. You'll block the UI until it completes anyway, which isn't a good idea. Do the whole thing in a background thread - then you can still use Invoke if you want, and while it's doing the computation the UI will still be responsive.
It sounds like you are deadlocking the UI thread. This makes perfect sense, as your button2_Click doesn't exit until For completes, and in particular, no message-loop events can be processed until button2_Click has completed. If you are on a different thread, Invoke uses a message-loop event, and does not return until that item is processed - so nothing will ever be done - and For / button2_Click will never complete.
By using BeginInvoke you simply queue this work - BeginInvoke returns immediately. This means that the For can complete, which lets button2_Click complete, which then allows the message-loop events to be processed (updating the UI).
I think it's because auf the Mainthread beeing blocked in the above Click event, waiting to finish AddListBoxItem, which is waiting the buttion2_click event to return.
You shouldn't have Controller logic in your UI, so the main problem that the Click isn't calling back a logic in a different thread. After Implementing an thread for your logic, your GUI wouldn't block and would refresh easy in any situation.