I was using code like this:
handler.Invoke(sender, e);
But the problem with that code is that it is synchronous and all it really does is update the GUI. It is not necessary for the server to wait for it to complete so it should be made asynchronous.
I don't really want to use BeginInvoke and EndInvoke because a callback method is not necessary in this case.
Is this a suitable alternative?
Task.Factory.StartNew(() => handler.Invoke(sender, e));
The way you did it is fine, another way to do this that works on .NET 3.5 is using the ThreadPool class instead
ThreadPool.QueueUserWorkItem(new WaitCallback((a) => handler.Invoke(sender, e)))
Also if handler happens to be a derived from control, you are allowed to call BeginInvoke without a corresponding EndInvoke.
Calls to GUI are special in that they must always be done from the GUI thread. In your own words, handler.Invoke(sender, e) "updates the GUI", yet it is (probably) not executed from the GUI thread, so it not OK in its current form.
In WinForms, you'll need to wrap your task delegate into Control.Invoke (or forget about tasks and just use Control.BeginInvoke).
If WPF, you can wrap your task delegate into Dispatcher.Invoke (or just use Dispatcher.BeginInvoke without a task).
I'm not familiar with C# 4's Task class, but I know BeginInvoke works just fine without EndInvoke. I sometimes write code like this:
handler.BeginInvoke(sender, e, null, null);
Edit: I was mistaken. While EndInvoke is not necessary to cause the code to execute on a new thread, the documentation clearly states that EndInvoke is important.
Related
I'm using the async / await pattern to perform some CPU heavy operations on an object (my method is awaitable), which works as supposed without blocking the UI thread.
However, when i pass the object as a parameter to the ctor of a new window (the new window is a logging window that needs access to the processed object), my UI thread blocks (which I kinda understand why).
to get around this I could wrap the execution of the calculation in a
Task.Run(async () => { await _myObject.PerformCalculations(); });
and then simply call
var logWindow = new LogWindow(_myObject);
logWindow.Show();
This works (of course) but i have a lot of dispatcher calls when the object raises events, which I wouldn't have to deal with if I could do without the Task.Run call.
So, my question is, can I somehow do without the Task.Run call and still pass the object to the logging window without blocking my UI thread?
EDIT
I'm sorry for the stripped down example, I actually intended to make the question as simple as possible to understand and failed miserably.
In a more general way: I have an object that raises events on certain conditions. When an event is raised, I want to perform updates on the UI. An event always fires from the thread that was created using Task.Run(...). Hence, dispatcher calls to the UI thread. So, I want to perform the calculations using async / await (already works) and pass the object to my logging window (blocks).
When I use Task.Run, everything works of course, but wherever I subscribe to an event of the object from the UI thread I have to use dispatcher calls to the UI thread, because the event fires from the thread that Task.Run created. These dispatcher calls I would like to avoid. In fact, if I wouldn't pass the object to the logging window, and call the Show() method, the UI thread wouldn't block and everything would work as supposed. No dispatcher calls needed in the event handlers.
It's kind of hard to get a clear picture of your situation. But it looks to me like you could do with some refactoring.
Consider PerformCalculations: this is a method returning Task (thus advertising itself as async-friendly) that does heavy CPU usage (thus not actually being async-friendly). The first thing I would look at is dividing up the logic in PerformCalculations so that the CPU-bound portions use their own Task.Run, leaving PerformCalcuations as an async method that doesn't (directly) hit the CPU:
public async Task PerformCalculationsAsync()
{
while (...)
{
await Task.Run(<next calculations>);
RaiseEvent();
}
}
The point of this refactoring is to divide the CPU code in Task.Run from the UI-ish code raising events. Also consider using the standard IProgress<T> approach if your events are logically progress updates or if this kind of refactoring would be too difficult for your code; IProgress<T>.Report can be called from any thread.
You may also find my posts on async constructors and async properties (particularly the data-binding section) to be helpful.
// awaitable as well - await this in another async void/Task method (e.g. commanding)
public async Task MyAsyncProcess()
{
await _myObject.PerformCalculations();
var logWindow = new LogWindow(_myObject);
}
Task.Run() executes an asynchronous method synchronously, so in this case you pretty much lack of use of the async/await pattern. Make the method where you execute your code async as well and await it somewhere else. Or alternatively use some FireAndForget logic.
Could you explain this for me please:
someformobj.BeginInvoke((Action)(() =>
{
someformobj.listBox1.SelectedIndex = 0;
}));
Could you tell me how can I use begininvoke exactly?
What is Action type?
Why there is blank brackets ()?
And what does this mean =>?
Action is a Type of Delegate provided by the .NET framework. The Action points to a method with no parameters and does not return a value.
() => is lambda expression syntax. Lambda expressions are not of Type Delegate. Invoke requires Delegate so Action can be used to wrap the lambda expression and provide the expected Type to Invoke()
Invoke causes said Action to execute on the thread that created the Control's window handle. Changing threads is often necessary to avoid Exceptions. For example, if one tries to set the Rtf property on a RichTextBox when an Invoke is necessary, without first calling Invoke, then a Cross-thread operation not valid exception will be thrown. Check Control.InvokeRequired before calling Invoke.
BeginInvoke is the Asynchronous version of Invoke. Asynchronous means the thread will not block the caller as opposed to a synchronous call which is blocking.
I guess your code relates to Windows Forms.
You call BeginInvoke if you need something to be executed asynchronously in the UI thread: change control's properties in most of the cases.
Roughly speaking this is accomplished be passing the delegate to some procedure which is being periodically executed. (message loop processing and the stuff like that)
If BeginInvoke is called for Delegate type the delegate is just invoked asynchronously.
(Invoke for the sync version.)
If you want more universal code which works perfectly for WPF and WinForms you can consider Task Parallel Library and running the Task with the according context. (TaskScheduler.FromCurrentSynchronizationContext())
And to add a little to already said by others:
Lambdas can be treated either as anonymous methods or expressions.
And that is why you cannot just use var with lambdas: compiler needs a hint.
UPDATE:
this requires .Net v4.0 and higher
// This line must be called in UI thread to get correct scheduler
var scheduler = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext();
// this can be called anywhere
var task = new System.Threading.Tasks.Task( () => someformobj.listBox1.SelectedIndex = 0);
// also can be called anywhere. Task will be scheduled for execution.
// And *IF I'm not mistaken* can be (or even will be executed synchronously)
// if this call is made from GUI thread. (to be checked)
task.Start(scheduler);
If you started the task from other thread and need to wait for its completition task.Wait() will block calling thread till the end of the task.
Read more about tasks here.
I have a library that is a complicated arbiter of many network connections. Each method of it's primary object takes a delegate, which is called when the network responds to a given request.
I want to translate my library to use the new .NET 4.5 "async/await" pattern; this would require me to return a "Task" object, which would signal to the user that the asynchronous part of the call is complete. Creating this object requires a function for the task to represent - As far as my understanding, it is essentially a lightweight thread.
This doesn't really fit the design of my library - I would like the task to behave more like an event, and directly signal to the user that their request has completed, rather then representing a function. Is this possible? Should i avoid abusing the "async/await" pattern in this way?
I don't know if I'm wording this very well, I hope you understand my meaning. Thank you for any help.
As far as my understanding, it is essentially a lightweight thread.
No, that's not really true. I can be true, under certain circumstances, but that's just one usage of Task. You can start a thread by passing it a delegate, and having it execute it (usually asynchronously, possibly synchronously, and by default using the thread pool).
Another way of using threads is through the use of a TaskCompletionSource. When you do that the task is (potentially) not creating any threads, using the thread pool, or anything along those lines. One common usage of this model is converting an event-based API to a Task-based API:
Let's assume, just because it's a common example, that we want to have a Task that will be completed when a From that we have is closed. There is already a FormClosed event that fires when that event occurs:
public static Task WhenClosed(this Form form)
{
var tcs = new TaskCompletionSource<object>();
form.FormClosing += (_, args) =>
{
tcs.SetResult(null);
};
return tcs.Task;
}
We create a TaskCompletionSource, add a handler to the event in question, in that handler we signal the completion of the task, and the TaskCompletionSource provides us with a Task to return to the caller. This Task will not have resulted in any new threads being created, it won't use the thread pool, or anything like that.
You can have a Task/Event based model using this construct that appears quite asynchronous, but only using a single thread to do all work (the UI thread).
In general, anytime you want to have a Task that represents something other than the execution of a function you'll want to consider using a TaskCompletionSource. It's usually the appropriate conceptual way to approach the problem, other than possibly using one of the existing TPL methods, such as WhenAll, WhenAny, etc.
Should I avoid abusing the "async/await" pattern in this way?
No, because it's not abuse. It's a perfectly appropriate use of Task constructs, as well as async/await. Consider, for example, the code that you can write using the helper method that I have above:
private async void button1_Click(object sender, EventArgs e)
{
Form2 popup = new Form2();
this.Hide();
popup.Show();
await popup.WhenClosed();
this.Show();
}
This code now works just like it reads; create a new form, hide myself, show the popup, wait until the popup is closed, and then show myself again. However, since it's not a blocking wait the UI thread isn't blocked. We also don't need to bother with events; adding handlers, dealing with multiple contexts; moving our logic around, or any of it. (All of that happens, it's just hidden from us.)
I want to translate my library to use the new .NET 4.5 "async/await" pattern; this would require me to return a "Task" object, which would signal to the user that the asynchronous part of the call is complete.
Well, not really - you can return anything which implements the awaitable pattern - but a Task is the simplest way of doing this.
This doesn't really fit the design of my library - I would like the task to behave more like an event, and directly signal to the user that their request has completed, rather then representing a function.
You can call Task.ContinueWith to act as a "handler" to execute when the task completes. Indeed, that's what TaskAwaiter does under the hood.
Your question isn't terribly clear to be honest, but if you really want to create a Task which you can then force to completion whenever you like, I suspect you just want TaskCompletionSource<TResult> - you call the SetResult, SetCanceled or SetException methods to indicate the appropriate kind of completion. (Or you can call the TrySet... versions.) Use the Task property to return a task to whatever needs it.
Is it good practice to invoke delegate for MainForm thread - this way?:
Txt.MainForm.EndInvoke(
Txt.MainForm.BeginInvoke(
new MethodInvoker(delegate()
{ // code here }
)));
No - because if you're calling EndInvoke, that will block until the delegate has completed. If you want that behaviour, just use Invoke instead.
To put it another way: if you're trying to do something other than blocking until your (presumably UI-modifying) delegate has executed in the UI thread, you should explain what that something is. If there isn't anything else, then Invoke will give you simpler code.
It doesn't make a lot of sense as the code fires up an asynchronous call and then immediately waits for the call to finish. I.e. you end up waiting on the calling thread.
Not considering the thing that other mentioned (I believe this EndInvoke - BeginInvoke chain is just an example usage of delegate): Using delegates is 100% OK. If this is the only usage of the delegate body, there's no need to define it as a named method. It is cleaner in the code and there's no need to jump through the file. Consider using newer syntax for delegates:
new MethodInvoker(() => { // code here })
Is BackgroundWorker in c# Thread Safe?
The reason I ask this is because I get a
Controls created on one thread cannot
be parented to a control on a
different thread
exception with it. This is my DoWork event code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var openFile = document.Open(MyFileName);
e.Result = openFile;
}
where document is an UI control that is initialized when the parent form is created. During Open method various properties in document will be filled.
I tried to change the code to invoke, yet the same problem persists. i.e,
document.GetType().GetMethod("Open)".Invoke(document, new object[]{MyFileName})
will yield the same error as the above.
Any idea how to manipulate the document control? In other words, how to make the above code work?
Edit: It was suggested that I use Control.Invoke, but it still didn't work ( both of the threads hanged). This is the code I tried:
private delegate bool OpenFile(string filePath);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
OpenFile oF = new OpenFile(document.Open);
var openFile = Invoke(oF, MyFileName); // it doesn't really matter whether I use BeginInvoke or Invoke, or other Control.Invoke, the end result is the same. Both the main thread hosting the document and the thread that launches the UI hanged.
e.Result = openFile;
}
It isn't the thread that's the problem it's the fact that it's trying to call a method on a UI control. In both WPF and WinForms controls can only be called on the UI thread (of which there is typically one). You don't say which you are using but you need to call the Control.Invoke method for WinForms or Dispatcher.Invoke for WPF.
The Invoke() reflection method you show will actually invoke the method on the current thread.
You can either invoke as Mehrdad Afshari suggested, or you can make use of the bgw's progress event which comes back on the UI thread. Or the work completed event which also comes back on the UI thread. The difference between the two is WorkCompleted is fired only once at the end. Progress is fired by you from DoWork.
While it's unclear to me what you exactly mean by thread-safety of a BackgroundWorker, the problem is not that object; Windows Forms controls are designed to be manipulated on a single thread (the UI thread). You should not manipulate Windows Forms objects on different threads. You can invoke actions in the UI thread from other threads by using the Control.Invoke method (the Invoke method you are currently using is provided by reflection and is totally unrelated to this problem):
Invoke(new Action(MethodToRunInUIThread));
void MethodToRunInUIThread() {
// do stuff here.
}
By the way, it doesn't make sense to use a background worker if all you are doing is manipulating UI objects.
If that functionality of the UI Control takes that long to execute, there may not be much you can do. "Freezing" occurs when a long-running operation happens on the UI thread, and if that function of the control was not specifically made thread-safe, it must be run on the main thread.
Normally, you'd want to separate the "document" functionality away from the control that displays it. This way, your document could be loaded on a separate, independent thread and be displayed later when ready. Otherwise, the control itself would have to implement a multi-threaded load routine to slow loading freezes.
Since you've specified this is a third party control in your comments, you may be out of luck here.
BackgroundWorker is a thread based structure. The thread-safety matter is about functions when doing simultaneous tasks. Maybe what you ask for is about winforms controls which are accessed through a unique thread, that of the user interface thread.
You need to use Control.BeginInvoke() in DoWork. This executes the delegate asynchronously and so will ensure the calling thread will not "hang".
Control.Invoke() will execute the delegate on the other thread also, but will cause the calling thread to wait for it to complete.
Generally in Windows Forms you are better off using Control.BeginInvoke() wherever possible to help avoid deadlocking between threads that can occur when one thread waits for another, as with Control.Invoke().
If the "document" object inherits from System.Windows.Forms.Control, you can simply call document.BeginInvoke(myDelegate).
However if it is actually some other component that encapsulates GUI controls, it may expose some way to call BeginInvoke. Check the documentation (if any). If there is no such ability, then unfortunately it is probably just not designed to support multi-threaded applications.
It looks like you are confused about the various Invoke/BeginInvoke types (understandable). This earlier question: What is the difference between Invoke and BeginInvoke? and Jon Skeets answer should help clarify things.
#Graviton, a related task with an answer is found here. The person was using BackgroundWorker to update a textbox, same concept applies (yours is only a single worker thread).