I have a pretty simple scenario:
I have an asynchronous WCF service calls in my silverlight app.
I want to execute those on a separate thread ( or similar) because they freeze up my UI.
All service calls are meant to update the ViewModel thus the/ a UI control on the page, so need to find a way to do that from the thread running the service calls without getting the familiar cross thread exception.
Any suggestions?
Many thanks.
In talking with folks on the WCF team, this is my understanding about how it works. If you simply make the call from a background thread, it won't work, as the WCF subsystem will marshal the call back onto the thread from which you initially opened the connection (normally, the UI thread). So what you have to do is create a worker thread, and then explicitly open the connection from that thread. Then, whenever you make a call, it will get marshaled back onto that thread. And of course, once you've received your callback and done your processing (on the background thread), then make sure that you marshal any UI changes back onto the UI thread using Dispatcher.BeginInvoke().
Dispatcher.BeginInvoke is the best solution.
Partial defination of service proxy:
public void GetItemById(int id, Action<ItemModel> callback)
{
AsyncCallback onCompleted = ar =>
Deployment.Current.Dispatcher.BeginInvoke(() =>
callback(this.Channel.EndGetItemById(ar)));
this.Channel.BeginGetItemById(id, onCompleted, null);
}
Call from MVVM:
var proxy = new MyServiceProxy();
proxy.GetItemById(5, item => this.Item = item);
You can either use a BackgroundWorker, or make your client proxy support the Asynchronous Pattern.
Make sure you dispatch UI updates to the proper thread as described here:
http://russelleast.wordpress.com/2010/02/27/using-wcf-async-pattern-with-silverlight-3/
Related
I implemented the observer design pattern in my application, but my app sends to an remote server requests via http protocol that take some time to resolve.
So, naturally, I did the sending an receiving part in a separate thread.
Can you please tell me how to make an window that observes the RequestObject to modify it's state based on the state of the request?
In the debugger step by step mode the window runes the code that I want it to do, but the window never refreshes its self.
Since I don't have a sample of your code I don't know the exacts of how you are updating your UI. If you are attempting to update the UI in the seperate thread that could be your issue. This may be of some help. http://msdn.microsoft.com/en-us/magazine/cc188732.aspx
You may also consider using the Task Parellel Library to perform your asyc operations.
http://msdn.microsoft.com/en-us/library/dd997423.aspx
I have added a ServiceReference to my Silverlight app. I have called it, WcfServiceReference. I can code the following
using ( var client = new WcfServiceReference.WcfDataServiceClient( ) )
{
client.GetSpendDataTotalAsync( Guid.NewGuid( ) );
}
I was thinking I should be able to reference client.GetSpendDataTotal (not Async), but it isn't available. However, it is in the app - I can find it in my service... Probably something obvious?
Silverlight only allows you to consume WCF services using async methods. The general idea is that synchronous calls to external services tie up the UI thread and leave your app unresponsive until they return. Take a look at this question and this blog post for more discussion on Silverlight and why you're guided into using async service calls. To quote from the blog post, "the whole purpose of the plug-in architecture only permitting async requests is so that plug-ins would not be able to lock up the browser".
Eric Lippert gives an excellent explanation/discussion of the problem of background work tying up the UI thread in this MSDN Magazine article about the upcoming async-await pattern. Definitely worth reading.
The main thing to remember here is that regardless of how much useful work might be happening in the background, if the UI is unresponsive the app is doing nothing as far as the user is concerned. Using asynchronous WCF service calls in Silverlight allows you to do something else with the UI whilst waiting for the result rather than leaving the user wondering why they can't do anything.
Silverlight doesn't allow non-asynchronous calls to services. When you code Silverlight access to WCF services, think Asynchronous.
Anyone found a good way to make asynchronous calls to the db via entity framework? Use background worker thread? This is a WPF application.
I know in RIA services there is a loadcompleted event that does not seem to exist in entity framework's object context.
Thanks!
I've written a blog post about async calls via commanding in a WPF application
http://devblog.terminto.com/2010/11/03/threading-as-command-in-mvvm/
At work I use the same technique and do calls to DB (EF4).
Is this useful, or are you asking about more entity framework-specific async methods?
Now I know about the Dispatcher and the DispatcherTimer and their benefits.
But I've always been under the impression that an async web-service/WCF callback (completed event handler) are automatically handled by the UI thread.
But looking at some references online such as the one linked below, it seems this is NOT the case.
So the strange thing is that i haven't been using the Dispatcher to update the UI (updating data-bound ObservableCollections) within service completed events, yet I've never received a cross-thread exceptions.
Can anybody explain why i havent seen this exception, or confirm if my original assumption is correct?
Reference:
http://www.silverlightshow.net/items/Tip-Asynchronous-Silverlight-Execute-on-the-UI-thread.aspx
What the dispatcher do is putting a message into the normal windows message queuse. If you update an element bound to an UI element you don't need to use a dispatcher because the PropertyChanged raised when you update your model already put a message into the windows message queue, so you don't need to call any dispatcher, otherwise you just do two round trips into the window message queue.
The easiest explanation is it depends on how you are retrieving your data and whether you are trying to update the UI. For instance, when using HttpWebRequest directly it will always need to be marshaled back to the UI thread. However if you are using WebClient then that is done for you. WCF will also do some marshaling for you.
"WCF proxies in Silverlight applications use the SynchronizationContext of the thread from which the web service call is initiated to schedule the invocation of the async event handler when the response is received."
http://tomasz.janczuk.org/2009/08/improving-performance-of-concurrent-wcf.html
In other words, WCF will marshal the call back to the thread in which it was called from. So if you are invoking your service calls from the UI thread, then they will come back on the UI thread. If you are invoking your services on a different thread then you will need to do the marshaling yourself.
Hope that helps.
Please help me with this one, I'm not sure what the correct, or best approach is. Basically I have a webservice which takes a byte stream, enabling a c# winform application to upload files to the webservice.
What I need is for the winform to upload in the background one file at a time (using basic multithread, it tries to upload them all at once). I also need to drop in there a progress bar.
How should I do it? Any ideas? I have the feeling it should be fairly straight forward. I think the application should start a new thread for the first file, wait until it's finished then dispose of the thread, create a new one for the next file and so on.
It completely depends on the technology you are using on the client side to access the web service.
If that technology allows for customization of the client proxy to the point where you can intercept transmission of messages (WCF allows this, I can't recall how much the old web services reference does), then you should be able to add your hook to see when the bytes are processed/sent.
Based on bookstorecowboy's comment about using the old "web reference" functionality in .NET, I believe that it generated proxies that derive from the SoapHttpClientProtocol class.
This being the case, I would recommend creating a custom class that derives from the SoapHttpClientProtocol class, overriding the GetWriterForMessage method. In this, you are supposed to return an XmlWriter given the Stream that is passed as a property on the SoapClientMessage parameter.
You would also create a custom class that derives from Stream which takes a Stream instance and forwards all the calls to that instance.
The only difference is that in the Write methods, you would fire an event indicating how many bytes were written.
You would then get the Stream that is exposed on the SoapClientMessage passed to the GetWriterForMessage and wrap it in your custom Stream implementation. You would also connect your event handlers here as well.
With that stream, you would create the XmlWriter and return it.
Then, for your proxies, you would use this new class that derives from SoapHttpClientProtocol and have the proxies derive from that.
As for ASP.NET 2.0 web services ("Old web services ") you could add web services extension to alter and extend it's behavior .
You could also add custom Http module .
It allows you aceess up to the stream level .
see Soap Extensions,Http Modules