Assume that I have Silverlight app doing a call to a WCF service:
void DoStuff()
{
MyProxy proxy = new MyProxy();
proxy.DoStuffCompleted += DoStuffCompleted;
proxy.DoStuffAsync();
}
void DoStuffCompleted(object sender, DoStuffCompletedEventArgs e)
{
// Handle the result.
}
DoStuff is called by the UI thread. What thread will eventually call the DoStuffCompleted method? If I invoke two async calls at the same time, is there a possibility that both the completed events are fired simultaneously, on different threads?
The callback will be invoked on the main thread. Multiple responses will not occur simultaneously. The order of the response events could be unexpected. You may want to use the overload of proxy.DoStuffAsync that accepts "user state" object:
proxy.DoStuffAsync(object userState)
This will allow you to send something unique for each call so you can differentiate which response you're dealing with. Remember that if the WCF call returns an error you have no return value - so userState may be the only way to know which call failed (if it matters).
Update:
Found some more info (on SO) on how to make it use another thread:
Silverlight web service callback performance Follow the link there to Tomek's blog for lots more info.
The Completed event will occur on a different thread than the UI Thread. Multiple Completed events may be executed simultaneously on different threads because a thread pool is used to handle results.
Asynch calls are executed in the background thread pool. For each asynch call you shall have a separate thread from the pool.
DoStuffCompleted will be executed in the background pool thread.
Now, it is important to note that this
method is called on the background
worker thread. If we want to update
the UI with the newly obtained data
(say we want to update a data grid
control to display the customer data),
we have to be careful to do this on
the UI thread. If we don't, then all
manner of strange things may happen
and we will have a difficult time
diagnosing which bug to fix (from here)
Related
I am writing a client server application that works like this:
Form1 loads and creates ServerHost. ServerHost is started to listen for TcpClient connections, on connected and accepted, ServerHost spawns a thread by way of ThreadPool.QueueUserWorkItem(DoWork, client);
Within the DoWork() thread, I want to update Winform Controls on Form1.
This is achieved by having events in ServerHost such as ServerHost.SomethingHappened. When something happened in DoWork(), it raises the event and the Form1.Handler is called to update the winforms control.
This set up gives me cross-thread operation error.
Is use of Control.Invoke and Control.InvokeRequired healthy? I am not good at threads, and MSDN is saying to use BackgroundWorker, but I can't see how to do it here. Any advice to change the structure to avoid using Invoke in this set up?
Control.Invoke is highly questionable, and Control.InvokeRequired is downright toxic.
If at all possible, use the new async/await support, and you won't need to explicitly marshal back to the UI thread. Also, use Task.Run instead of ThreadPool.QueueUserWorkItem for background work.
The problem with Control.Invoke is that it ties your library to a specific UI (WinForms). Capturing a SynchronizationContext is a step above that, and implicitly capturing the SynchronizationContext by using await is even better.
You have to invoke the code that updates the user interface on the UI thread.
In general there are several options to do that:
calling Invoke on a Control
using a BackgroundWorker that has been started on the UI thread
calling Post on the SynchronizationContext of the UI thread
using Task.ContinueWith with the TaskScheduler of the UI thread
using asynchronous calls with async/await
In my opinion last method is by far the easiest for the developer, but it is only available with C# 5 and .NET 4.5 or .NET 4.0 with the Microsoft.Bcl.Async package. Tasks are nearly as easy to use but both of these methods would require you to change your code. They won't work to simply invoke a method on the UI thread from a thread pool thread.
The BackgroundWorker is usually used to schedule an action that takes quite some time. Its ReportProgress method raises the ProgressChanged event on the thread that called the RunWorkerAsync method. As such it is also not a good solution to your problem.
SynchronizationContext.Post and Control.Invoke work similarly, but Control.Invoke doesn't require you to capture the UI context, so it's easier to use.
To summarize it you should use Control.Invoke unless you want to change your code to make use of async/await.
It's fine as long as the UI thread isn't overburdened by those invokes. It does introduce some latency to the communication, which usually isn't an issue, however, it can become more of a problem if you're doing a lot of Invokes, or if the UI thread is doing a lot of work (eg. rendering complex graphs or something like that). Invoke is a synchronous method - it will not return until the invoked command is actually processed, and returns its return value.
As long as you're not tied up by these issues, all is well. Profiling and performance testing is critical to allocate your resources correctly, guessing is usually a huge waste of time and resources.
If you don't need the resulting value (or at least not synchronously) and you're starting to get into performance trouble, have a look at BeginInvoke, which handles the invoking asynchronously. This means your networking thread doesn't have to wait for the UI thread to work. This is quite critical in high performance servers with thousands of connections. They simply can't afford to wait while the UI does its thing.
However, do note, that having a server socket running on a different thread is not a good solution for larger servers, and in fact, it's no longer the easiest solution either. .NET now has great support for asynchronous calls and callbacks, making implementations of asynchronous processing a breeze. In your typical Winforms application, it means that I/O blocking applications can work without having constantly running and polling threads. For example, waiting for a new connection can be as simple as:
var connection = await listener.AcceptTcpClientAsync();
That's it. Automagically, all the callbacks will be processed at the right time, without blocking the processing, all of your own code always running on the main UI thread. In other words, you can easily do this:
while (!aborted)
{
var connection = await listener.AcceptTcpClientAsync();
tbxLog.Text += "New connection!\r\n";
}
While this seems like an infinite loop blocking the UI thread indefinitely, the reality is that when the application gets to the await keyword, it will register an asynchronous callback and returns. Only when the asynchronous callback is actually invoked (by IOCP in this case) is the code resumed (on the UI thread), and tbxLog has the text appended, followed by waiting for another connection.
I've never had problems doing it this way. No matter how you set it up, updating your controls has to be done on the thread they were created on. If you use a BackgroundWorker or some other async construct, somewhere an invoke is going to be called. I typically create a method on the form like:
delegate void TextSetter(string text);
internal void SetText(string text)
{
//call on main thread if necessary
if (InvokeRequired)
{
this.Invoke((TextSetter)SetText, text);
return;
}
//set the text on your label or whatever
this.StatusLabel.Text = text;
}
I've used that method in a number of applications and it's never been a problem, even updating many times per second.
As far as I'm aware, the only way to get around calling an invoke is to have your main thread constantly poll for updates, which is generally accepted as a really bad way to do things.
A really obvious simplification is to abstract away the InvokeRequired/Invoke into an extension method for a Control.
public static class FormExt {
public static void Execute(this Control c, Action a) {
if (c.InvokeRequired) {
c.Invoke(a);
} else {
a();
}
}
}
Now you just wrap up normal form updates into a lambda and execute them.
form1.Execute(() => form1.Text = "Hello world");
In my winforms client application, I have generated asynchronous methods for my WCF service (Begin... and End...).
When the application starts, it makes async calls to the server to get and cache data that will be later used in the application (e.g. list of countries).
If the application's main thread requires this data (e.g. to fill a combobox) before the async call had a chance to complete, I would like to block the main thread until the async call had Ended. I want to avoid making redundant calls to the WCF server.
I have tried to use a Monitor/Mutex and called Monitor.Enter(countryLock) then BeginGetCountries in the main thread and Monitor.Exit(countryLock) when the EndGetCountries method is called. However, I am facing the following exception:
Object synchronization method was called from an unsynchronized block of code.
Am I supposed to call Monitor.Exit(...) on the same thread that called Monitor.Enter(...)? If yes, how can I know the owner of the Monitor object and make a call in its context?
No, you don't want really to block the main thread. What you want to do is set a flag that the operation is pending and disable parts of your UI that depend on the result. When the result is returned from the asynchronous WCF operation, you can enable those parts of the UI and populate the data.
if you block the main thread it will give the appearance that the application has halted and that will be a poor experience for your users.
Like Peter Richie said, you don't want to lock in your UI thread. A "busy" flag is all you need, really.
Secondly, trying to do this with Monitor.Enter like you describe would not work, as the same thread is allowed to enter the same monitor twice without blocking.
And if you do lock, then yes, you are supposed to call Monitor.Exit(...) on the same thread that called Monitor.Enter(...). If that was the only only problem, you could marshal this back to the UI thread with this.BeginInvoke(). But like I said, locking with Monitor in a single threaded scenario makes no sense.
I am writing a library, and would like to be able to fire a callback on a specified thread, so the end-user does not have to worry about thread-safety.
I tried using ExecutionContext, but that didn't work out too well, it would fire in the specified context (a new thread), but not on the thread that originally called the function.
The code should work like this:
void Connect() {
// This should be in the same thread ..
SocketAsyncEventArgs.Completed += eventHandler;
Socket.ConnectAsync(SocketAsyncEventArgs)
}
void eventHandler() {
// .. as this
}
You can't just run your code on some existing thread. That thread is already executing other code. But, it can provide you some way to run your code on it. The main thread in a WPF application does this using Dispatcher.Invoke(). The main thread of a WinForms application uses Control.Invoke().
There is a more general way to do this: use Synchronization.Context.Current. This would work for the main thread of WPF or WinForms application, but would execute the callback on a thread pool thread otherwise. (Unless there is some sort of custom synchronization context, which I think is very rare.)
But this is the best you can do. Like I said, you can't run your code on some other thread when you want. The code in that other thread has to allow you to do that.
That's the thing about asynchronous functions -- you can't guarantee when you'll get called back, or what thread will be running your callback function. Consider that the cost of being able to "set it and forget it".
There's usually no need for that much control anyway. If you "need" to have a specific thread run your callback, what you really need is to review why that's necessary. If it's something that needs to run on the UI thread, there's Control.Invoke. (The UI thread anticipates needing to be handed stuff to do, because of how the architecture works, so controls have a way to pass callbacks to run on that thread. You can't just up and do that with arbitrary threads -- they have to be expecting to be passed a callback like that.) Otherwise, if you have an issue with locks or something, chances are you're trying to use asynchronous functionality to do stuff that should really be done synchronously in a separate thread.
I haven't been able to find an example like this, though I'm sure there must be a few out there.
When the user clicks a button to log in, an event handler on the button click calls a function that logs the user in. Based on the user, they can be taken to one of many start screens. The information for which screen is returned from a service call. From what I can tell, Dispatcher.BeginInvoke is only used to update the UI thread, so the logic that determines which page to navigate to should be in the method passed to Dispatcher.BeginInvoke, right?
I need to make a service call and take action based on the result. Do I have to make the async service call first and call Dispatcher from the callback? Do I put the function that does the validation, calls the service, and handles the callback as the delegate that is passed to the Dispatcher?
Sorry if this is a basic question. The examples I've found only use the Dispatcher to update a textbox or some other trivial item. I haven't found anything where the UI thread needs to take action based on the result of an async call.
It's not clear what validation you're talking about but:
Call the service asynchronously, with a callback to execute when the service call finishes
In the callback, do whatever non-UI related work is involved, and then call Dispatcher.BeginInvoke to perform any UI-related operations.
If you need to do validation before the service call, that could be part of your button's event handler... at least as long as it isn't a long-running piece of validation.
If you could give more details about what steps are logically involved in your process, that would help.
See, Dispatcher actually holds the UI thread. As every control has strong thread affinity, you need to update this using Dispatcher.
From any thread you can access Dispatcher using DispatcherObject.Dispatcher.
this.Dispatcher.Invoke((Action)(()=>{
.//// your action
});
Now whenever you need to update the elements in the thread, you can wrap around the context to call service anytime. You can use the Background thread or you can call from inside of Dispatcher thread to invoke the Service call.
Calling From dispatcher will hold the UI if the call is synchronous. So I recommend you to do the call from the Background thread just below updating the Invoker.
All service call are asynchronous in silverlight (and hence windows phone 7) so yes, what you describe is way you do it.
Different service libraries provide different ways to call their methods - some offer a 'call complete' method, others take a event hander passed in, but either way if you want to update the UI (and I assume this includes moving page) you will need to do this on the UI thread, which is what the dispatcher is for.
Dispatcher.BeginInvoke( () => {
// This code is on the UI thread.
});
I currently have a thread that listens for data from the network and then runs rules on it. I then want to pass the data to the GUI. I am worried about having a deadlock in the GUI. I cant figure out were to put the mutexes on the GUI side. I am also using c# and dotnet 3.5.
What I have come up with is
1) Using a timer to create an event and dump the thread. Worried about performance.
2) Use an intermediary event to copy the data to GUI.
3) Dig in and figure out thread safe way of using GUI.
What do you think is best way to proceed?
Edit: Here is the solution I am using. I pass in the changed element and then protect the big object with a mutex. I use helper function to switch threads using InvokeRequired then BeginInvoke with a delegate. Pulled from reading the answers and then following links until reaching Threading in Windows Forms by Jon Skeet.
delegate void UInt32ParameterDelegate(UInt32 n);
public void UpdateLocation(UInt32 n)
{
if (InvokeRequired)
{
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new UInt32ParameterDelegate(UpdateLocation), new object[] { n });
return;
}
// Must be on the UI thread if we've got this far
this.engine.location.UpdateBusy.WaitOne();
// do the work in here
this.engine.location.UpdateBusy.ReleaseMutex();
}
Synchronization is very easy in Windows Forms. You can call Control.Invoke() in the background thread. The thread will stall until the delegate has finished running on the UI thread. No sync required at all.
If stalling the thread is a problem, use Control.BeginInvoke(). You'll have to protect the object(s) you pass to the delegate with a lock if the thread might alter them while it continues running. That's rarely the case in a producer-consumer scenario, the thread can simply create new objects.
Do make sure that you don't Invoke() too often. Do it more frequently than about 1000 times per second and the UI thread will stop pumping Windows messages, being bogged down by handling the invoke requests. Since it is human eyes you're trying to please, invoking more than about 25 times per second is just wasted effort. Pool intermediate results in a collection object.
I hope I understand your problem correctly.
After the background thread reads the data and does whatever it wants, it should use Invoke to call a method on the GUI thread. That method would update anything that should be updated in the GUI.
Never read from the network on the GUI thread. It's only a matter of time before your application runs during a network outage and your GUI hangs as a result. This will really frustrate your users.
In your situation I think the best approach is to have a background thread complete the read operation. Then take the resulting data and move it back to the GUI thread via a SynchronizationContext Post or Send method.
you should just pass an event from your network thread to your UI thread.
then cross threads using begininvoke so you don't get a cross thread exception.
Need help getting info across a UI thread and another thread in C#
You could use a backgroundworker that will process the datareading in a background thread and when it's done you can end the backgroundworker triggering it's RunWorkerCompletedEventHandler. In the RunWorkerCompletedEventHandler you can update your GUI thread with the result.
Isn't easier to just throw a delegate who raise an event that inform the form to refresh itself?