Im not sure, but is it called inlining when you do it all in one line?
I my code i have this BackgroundWorker. The DoWorker enforce a sleep of on sec and the RunWorkerCompleted just does noe bit of code. Would it be possible to instead of defining a function do it all in one line like
.DoWork += ((sender, arg) => { ... });
and
.RunWorkerCompleted += ((sender, arg...
What is the right syntax for this, and what is this called? Its nice to keep things simple when you have a simple task at hand :-)
You are confusing inlining with lambda expressions.
Inlining is replacing the calling of a method by its body, for example:
int TimesTwo(int x)
{
return x * 2;
}
//before inlining:
int a = TimesTwo(6) + TimesTwo(7);
//after inlining:
int a = 6 * 2 + 7 * 2;
This is a compiler optimization technique to avoid method call overhead.
For your BackgroundWorker example the correct syntax would be:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (sender, e) => RunMyMethod();
//or
worker.DoWork += (sender, e) => { RunMyMethod(); }
For more information see MSDN.
Related
I have created the following extension method to wait for a page to load when using the WebBrowser control.
public static Task<bool> WaitLoad(this WebBrowser webBrowser, int wait)
{
var timerInternalWait = new Timer {Interval = 1000, Tag = "Internal"};
var timerMaxWait = new Timer {Interval = wait};
var tcs = new TaskCompletionSource<bool>();
WebBrowserNavigatingEventHandler navigatingHandler = (sender, args) => timerInternalWait.Stop();
webBrowser.Navigating += navigatingHandler;
WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (sender, args) => { timerInternalWait.Stop(); timerInternalWait.Start(); };
webBrowser.DocumentCompleted += documentCompletedHandler;
EventHandler timerHandler = null;
timerHandler = (sender, args) =>
{
webBrowser.Navigating -= navigatingHandler;
webBrowser.DocumentCompleted -= documentCompletedHandler;
timerInternalWait.Tick -= timerHandler;
timerMaxWait.Tick -= timerHandler;
timerMaxWait.Stop();
timerInternalWait.Stop();
tcs.SetResult(((Timer) sender).Tag.ToString() == "Internal");
};
timerInternalWait.Tick += timerHandler;
timerMaxWait.Tick += timerHandler;
return tcs.Task;
}
I have a couple of question around it though:
When, if ever, do the timers cease to exist and get GCed? I suppose the same question applies for the lambda expressions.
And if currently the answer is never, is there something I can do to ensure that they are cleaned up when no longer needed?
Lastly, ReSharper gives me an implicitly captured closure on the navigatingHandler and the documentCompletedHandler definitions. How can I prevent this from happening?
Really tricky question.
Your timer won't be garbage collected until the task you returned has finished.
Why? ok, here is the tricky part. That's because of the closure ReSharper is telling you about!
All the variables used inside the lambda are kept alive by the framework with a reference to ensure they exist when the lambda is executed and to restore them for it's use. Because you are using the timer inside the lambda the timer will be kept alive while the lambda exists, and the lambda will exists at least until the last line of the lambda has been executed, setting the result of the task.
So it's sure to assume the timer will be kept alive until the lambda has been executed.
To update the UI from an other thread you need to call the BeginInvoke method of the dispatcher. Before you invoke you method you can check whether the calling thread is associated with the dispatcher.
For my example I have 2 ways to update a textbox; by clicking a button and by elapsing a timer. The Code:
using System;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
private int i = 0;
private TextBlock myText = new TextBlock();
private Button myButton = new Button();
private Timer timer = new Timer(2 * 1000);
private StackPanel panel = new StackPanel();
public MainWindow()
{
InitializeComponent();
myButton.Content = "Click";
panel.Children.Add(myText);
panel.Children.Add(myButton);
this.AddChild(panel);
myButton.Click += (_, __) => IncrementAndShowCounter();
timer.Elapsed += (_, __) => IncrementAndShowCounter();
timer.Start();
}
private void IncrementAndShowCounter()
{
i++;
if (this.Dispatcher.CheckAccess())
{
myText.Text = i.ToString();
}
else
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
myText.Text = i.ToString();
}));
}
}
}
}
When I don't CheckAccess() and just always execute the BeginInvoke everything works fine.
So my question is why not always use the BeginInvoke and skip the CheckAccess?
So my question is why not always use the BeginInvoke and skip the
CheckAccess?
That's exactly what you should do most of the time if invoking is required (i.e. you are touching a control owned by another thread). If invoking is not required then you should skip both of them.
Using CheckAccess implies that your code doesn't know or doesn't want to assume that it will run on the "correct" thread. There are two main reasons for this: genericity (your code is in a library and you can't predict how it will be used) and convenience (you want only one method to take care of both cases, or you want the freedom to change the mode of operation without breaking the program).
Your example falls in the second category: the same method services both modes of operation. In this case you have three possible options:
Always invoke without CheckAccess.
This is going to give you a performance hit (a negligible one here), and it will also make readers of the code assume that the method is only called from worker threads. Since the only benefit is that you will be writing a little less code, this is the worst option.
Keep everything as it is.
Since IncrementAndShowCounter is called from both UI and worker threads, making it adapt to the situation lets you move on to other problems. This is simple and good; it's also the best you can do when writing library code (no assumptions allowed).
Never invoke from within the method, do it from outside as required.
This is the best option on technical merit: since you know the context in which the method will be called, arrange for the invocation to happen outside it. This way the method is not tied to any specific thread and you don't get unnecessary performance penalties.
Here's example code for the third option:
private void IncrementAndShowCounter()
{
i++;
myText.Text = i.ToString();
}
myButton.Click += (_, __) => IncrementAndShowCounter();
timer.Elapsed += (_, __) => Dispatcher.BeginInvoke(IncrementAndShowCounter);
If you 100% sure that the calling thread is UI thread - you can use the "DO" method directly.
If you 100% sure that the calling thread is not UI thread, but the operation should be done on the UI thread, you just call the BeginInvoke
....
// 100% I'm sure the Click handler will be invoked on UI thread
myButton.Click += (_, __) => IncrementAndShowCounter();
// here I'm not sure
timer.Elapsed += (_, __) => Dispatcher.BeginInvoke(IncrementAndShowCounter);
// 100% not UI thred here:
Task.Factory.StartNew(() => Dispatcher.BeginInvoke(IncrementAndShowCounter), TaskScheduler.Default)
private void IncrementAndShowCounter()
{
i++;
myText.Text = i.ToString();
}
I have a WPF C# projects with the below buttonClick event void:
public void ButtonClick(object sender, RoutedEventArgs e)
{
_worker.WorkerReportsProgress = true;
_worker.DoWork += (o, ea) =>
{
try
{
_class1.hithere();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
};
_worker.ProgressChanged += (o, ea) =>
{
};
_worker.RunWorkerCompleted += (o, ea) =>
{
MessageBox.Show("Done");
};
_worker.RunWorkerAsync();
}
I have a folder in the application called InformationProviders than contains the Class1.cs file and I have implemented the correct using MyApplication.InformationProviders; statement in the MainWindow.xaml.cs file that contains the button click event above.
I have also declared the Class1 class that is then called upon in the backgroundworker DoWork event correctly as such:
readonly Class1 _class1 = new Class1();
The Class1.cs file contains this little code made just to see if it worked and it doesn't unfortunately:
public class Class1
{
public void hithere()
{
MessageBox.Show("Hi, I'm working.");
}
}
What am I missing here???? I declared the class as public and (I believe) declared all that needed to be declared to make the process work...
All it does is display a message saying "Done", meaning it has completed the backgroundworker process (even though it did not do anything at all that was stated in the DoWork event. So pretty much, launching the worker and immediately considering it finished.
Regards and thanks,
Simon
Here's the tricky thing about running a multi-threaded application: only one thread has access to the UI and perform operations on it.
In case of your code, the BackgroudWorker in it's background operation attempts to show a message using MessageBox. This won't work - it's not being "fired" on the UI thread!
If you absolutely MUST perform UI operations from inside the BackgroundWorker (which you shouldn't do - this is what the ProgressChanged event is for) then you can use a Dispatcher class.
Here's a short example:
private void Button_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, a) =>
{
this.Dispatcher.Invoke(new Action(() => MessageBox.Show("doing stuff")));
};
bw.RunWorkerCompleted += (s, a) =>
{
MessageBox.Show("done");
};
bw.RunWorkerAsync();
}
Also fun fact, if you use Dispatcher.Invoke (as written above), then "doing stuff" will appear first, if you use Dispatcher.BeginInvoke then "done" will appear first, because the other operation will be queued on the UI thread.
Here's the "politically correct" way to use the BackgroundWorker:
bw.WorkerReportsProgress = true;
bw.DoWork += (s, a) =>
{
bw.ReportProgress(0, "doing stuff");
};
bw.ProgressChanged += (s, a) =>
{
MessageBox.Show(a.UserState as String);
};
I found the problem, i was using the Xceed.WPF.toolkit version of the MessageBox and it was just refusing to show that UI element in a backgroundWorker. Thanks for the help though it pointed me in the right direction. hoping this will help other people
I am currently working on a project in C#. I have a method called updateProgress() which has two int parameters (count and totalRows).
If I have call the method by saying updateProgress(count, totalRows) this works fine but I want to run this method within a new thread.
How can I go about doing this, I have looked online and everything looks overly complicated for what I am wanting to do.
Thanks for your help with this
Something like this:
new Thread(delegate () {
updateProgress(count, totalRows);
}).Start();
Be aware that threading actually is quite a complex topic, so if you have troubles understanding the asynchronous APIs available in the .NET Framework, I doubt if you should start using threads in the first place.
Anyway, you have several options:
Spin off a thread by your own (like cdhowie pointed out), which is rather discouraged.
Use the TPL (task parallel library) if you are running on .NET 4. Here is a good introduction.
TaskFactory.StartNew(() => updateProgress(count, totalRows));
Use the ThreadPool if you are running on an older version of .NET.
ThreadPool.QueueUserWorkItem(s => updateProgress(count, totalRows));
Of course there are other ways too, but this are imo the most important ones.
Best Regards,
Oliver Hanappi
This has been almost a year, and my answer will not add anything "new" to what has already been said in other answers.
If someone is using .Net 4.0 or higher, best options would be to use a task and let the framework decide the best, by calling TaskFactory.StartNew(...). For older versions, still it's better to utilize the thread pool by using ThreadPool.QueueUserWorkItem(...).
Now, if still someone wants to use the thread in the basic way (creating new thread) for some reason, then this
new Thread(delegate () {
updateProgress(count, totalRows);
}).Start();
can be written in a little cleaner way, using the lambda expression, like this
new Thread(() => updateProgress(count, totalRows)).Start();
There are different ways to run a method in a different thread, like Thread, BackgroundWorker, ThreadPool or Task. Which one to choose depends of various things.
From the name of the method, it sounds like the method should show some progress in the GUI of your application. If that's the case, you have to run the method on the GUI thread. If you want to call it from another thread, you have to use Dispatcher.Invoke() in WPF and Control.Invoke() in WinForms.
try following
ThreadPool.QueueUserWorkItem((o) => { updateProgress(5, 6); });
Here's a more complex example without anonymous delegates. Look at result in the completed function.
using System;
using System.Threading;
using System.ComponentModel;
class Program
{
static BackgroundWorker _bw;
static void Main()
{
_bw = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
_bw.DoWork += bw_DoWork;
_bw.ProgressChanged += bw_ProgressChanged;
_bw.RunWorkerCompleted += bw_RunWorkerCompleted;
_bw.RunWorkerAsync ("Hello to worker");
Console.WriteLine ("Press Enter in the next 5 seconds to cancel");
Console.ReadLine();
if (_bw.IsBusy) _bw.CancelAsync();
Console.ReadLine();
}
static void bw_DoWork (object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 100; i += 20)
{
if (_bw.CancellationPending) { e.Cancel = true; return; }
_bw.ReportProgress (i);
Thread.Sleep (1000); // Just for the demo... don't go sleeping
} // for real in pooled threads!
e.Result = 123; // This gets passed to RunWorkerCompleted
}
static void bw_RunWorkerCompleted (object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
Console.WriteLine ("You canceled!");
else if (e.Error != null)
Console.WriteLine ("Worker exception: " + e.Error.ToString());
else
Console.WriteLine ("Complete: " + e.Result); // from DoWork
}
static void bw_ProgressChanged (object sender,
ProgressChangedEventArgs e)
{
Console.WriteLine ("Reached " + e.ProgressPercentage + "%");
}
}
I'm gonna create a BackgroundWorker with an anonymous method.
I've written the following code :
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(
() =>
{
int i = 0;
foreach (var item in query2)
{
....
....
}
}
);
But Delegate 'System.ComponentModel.DoWorkEventHandler' does not take '0' arguments and I have to pass two objects to the anonymous method : object sender, DoWorkEventArgs e
Could you please guide me, how I can do it ?
Thanks.
You just need to add parameters to the anonymous function:
bgw.DoWork += (sender, e) => { ... }
Or if you don't care about the parameters you can just:
bgw.DoWork += delegate { ... }
If you specify a lambda, you must ensure it takes the same number of arguments:
bgw.DoWork += (s, e) => ...;
But if you're not using the arguments, you could just use an anonymous delegate without parameters:
bgw.DoWork += delegate
{
...
};
If you have written the above without lambdas how it would be?
backgroundWorker1.DoWork +=
new DoWorkEventHandler(backgroundWorker1_DoWork);
and the named method:
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
// Assign the result of the computation
// to the Result property of the DoWorkEventArgs
// object. This is will be available to the
// RunWorkerCompleted eventhandler.
e.Result = ComputeFibonacci((int)e.Argument, worker, e);
}
But now you are using lambdas with no bound variables ()=>
You should provide two objects sender and e (which they will get type inferred later).
backgroundWorker1.DoWork += (sender, e) => ...
Lets make it simple
Lambda expressions are really handy to make the code shorter and more readable. However entry level programmers might find it a bit difficult to deal with. There are three separate concepts one should go through: anonymous methods, delegates and lambda expressions. A detailed walk-through of each of them is beyond the scope of this answer. I hope that the code example given below will serve the purpose of giving a quick view of the different approaches available.
class TestBed
{
BackgroundWorker bgw = new BackgroundWorker();
void sample()
{
//approach #1
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
//DoWorkEventHandler is nothing but a readily available delegate written by smart Microsoft guys
//approach #2, to make it a little shorter
bgw.DoWork += (s,e) =>
{
//...
};
//this is called lambda expression (see the => symbol)
//approach #3, if lambda scares you
bgw.DoWork += delegate
{
//... (but you can't have parameters in this approach
};
//approach #4, have a helper method to prepare the background worker
prepareBgw((s,e)=>
{
//...
}
);
//approach #5, helper along with a simple delegate, but no params possible
prepareBgw(delegate
{
//...
}
);
//approach #6, helper along with passing the methodname as a delegate
prepareBgw(bgw_DoWork);
//approach #7, helper method applied on approach #1
prepareBgw(new DoWorkEventHandler(bgw_DoWork));
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
//...
}
void prepareBgw(DoWorkEventHandler doWork)
{
bgw.DoWork+= doWork;
}
}
Note that we used "delegate" and not "Delegate" in this example (there is a difference between the two)