Queueing WCF calls from silverlight - c#

In my Silverlight usercontrol I am listening to events from the application and calls a WCF service to do some action
void SelectedCustomerEvent(string customer)
{
//.......
_wcfserviceagent.GetCustomer(customer, callback);
}
void callback(ObservableCollection<CustomerType> customer)
{
//do some action
}
In certain scenarios the event gets fired more than once when doing certain actions. The trouble is the callback is not necessarily called in the order of calls to the WCF service.
Is there anyway to make sure the calls and callback are always called in order?
Ideally, I want the the execution in such a way that for an event it will call the service and callback, and any other calls come in between will get queued. Of course, I can't block the UI thread.

The only way to ensure the sequence of calls to the WCF service is to implement your own queue on the client.
For example:
Queue<string> _customersQueue = new Queue<string>();
bool _fetching;
void SelectedCustomerEvent(string customer)
{
_customersQueue.Enqueue(customer);
//.......
if (!_fetching)
{
DoFetchCustomer(_customersQueue.Dequeue());
}
}
void DoFetchCustomer(string customer)
{
_fetching = true;
_wcfserviceagent.GetCustomer(customer, callback);
}
void callback(ObservableCollection<CustomerType> customer)
{
_fetching = false;
//do some action
if (_customersQueue.Count > 0)
{
DoFetchCustomer(_customersQueue.Dequeue());
}
}

Related

ASP.NET MVC 4 Web API: How to Asynchronously Process a Request that Needs to Extract Results from an Asynchronous WCF Service Callback

Suppose I implemented a webservice using ASP.NET MVC 4 that has a controller that exposes one method:
Response Process(Request request);
This webservice communicates with a middle-tier service for processing requests. The middle-tier service contract service looks something like this:
[ServiceContract(CallbackContract=typeof(IServiceCallback))]
interface IService
{
[OperationContract(IsOneWay=true)]
void Process(Request request);
}
interface IServiceCallback
{
[OperationContract(IsOneWay=true)]
void Processed( Response response );
}
This service asynchronously processes a request via the matching Process/Processed methods.
What's the best way to asynchronously make a call to from the web service to this middle-tier service? I'm having trouble seeing how to get the response from the callback thread to return to the calling client, when the callback method obviously returns in a different worker thread?
Thanks for any help given.
You have to use async and await. Read this link
http://msdn.microsoft.com/en-us/library/vstudio/hh300224.aspx
Try this in your calling code.
public void DoStuff()
{
using(var proxy = new Proxy())
{
var result = await proxy.Process();
Task.Run(() => Processed(result));
}
}
Or this...which works with .net 4
public void DoStuff()
{
using(var proxy = new Proxy())
{
proxy.Process().ContinueWith(result => Processed(result), TaskCreationOptions.None);
}
}

WCF Calling a service property from a callback without deadlock

Can someone kindly show me how to call a property of a WCF service from within a callback without deadlock occurring?
I've tried adding [CallbackBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)] to the class which implements the callback, but without success.
The service has the following attribute:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
public class SAPUploadService : ISAPUploadService
{
Thanks MM
Here's the code which calls the Callback method
foreach (var otherConnection in _users.Keys)
{
SAPUploadInstruction ins = AddMessageToInstruction(message);
ins.UserName = user.UserName;
Task.Factory.StartNew(() =>
{
otherConnection.ReceiveInstruction(ins);
});
and here's the callback implementation of the ReceiveInstruction
public void ReceiveInstruction(SAPUploadInstruction instruction)
{
// fire this objects call back....
if (OnReceiveInstruction != null) OnReceiveInstruction(this, instruction);
}
In the above, the event OnReceiveInstruction is attached to the UI. This is handled as follows:
public void ReceiveInstruction(object sender, SAPUploadInstruction instruction)
{
DispatchIfNecessary(() => {
ProcessInstruction(instruction);
});
}
The method above - ProcessInstruction - sets various controls according to the service properties/functions. It is this that is getting deadlocked i.e Label1.Content = myService.SomeProperty.
BTW, DispatchIfNecessary is implemented as :
public void DispatchIfNecessary(Action action)
{
if (!Dispatcher.CheckAccess())
Dispatcher.Invoke(action);
else
action.Invoke();
}
In DispatchIfNecessary use asynchronous version of Invoke, so your callback won't wait for finishing UI changes, that can't be done because UI thread is waiting for end of callback processing (hence we have deadlock):
Dispatcher.BeginInvoke(action);

Need help implementing async calls in C# 4.0 Web Service Client

So I'm working on a client that consumes a web service. I used the WSDL and XSD files from the service to generate the proxy class, and all of the synchronous functions work fine. However, given their synchronous nature, making any of the calls causes the UI to stop responding until the call is finished. Classic reason for using async methods, right?
Problem is, I'm still in school for my degree and know little about asynchronous programming. I've tried to read up on it online (my employer even has a Books 24x7 subscription) but I'm having a hard time grasping how I should make the calls and how to handle the response. Here's what I have:
/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://localhost:8080/getRecords", RequestNamespace="http://www.<redacted>.com/ws/schemas", ResponseNamespace="http://www.<redacted>.com/ws/schemas", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlArrayAttribute("records", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
[return: System.Xml.Serialization.XmlArrayItemAttribute("list", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public record[] getRecords([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] string username, [System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)] [System.Xml.Serialization.XmlArrayItemAttribute("list", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="integer", IsNullable=false)] string[] ids) {
object[] results = this.Invoke("getRecords", new object[] {
username,
ids});
return ((record[])(results[0]));
}
/// <remarks/>
public void getRecordsAsync(string username, string[] ids) {
this.getRecordsAsync(username, ids, null);
}
/// <remarks/>
public void getRecordsAsync(string username, string[] ids, object userState) {
if ((this.getRecordsOperationCompleted == null)) {
this.getRecordsOperationCompleted = new System.Threading.SendOrPostCallback(this.OngetRecordsOperationCompleted);
}
this.InvokeAsync("getRecords", new object[] {
username,
ids}, this.getRecordsOperationCompleted, userState);
}
private void OngetRecordsOperationCompleted(object arg) {
if ((this.getRecordsCompleted != null)) {
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.getRecordsCompleted(this, new getRecordsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
There's also this:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class getRecordsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
private object[] results;
internal getRecordsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState) {
this.results = results;
}
/// <remarks/>
public record[] Result {
get {
this.RaiseExceptionIfNecessary();
return ((record[])(this.results[0]));
}
}
}
and this:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
public delegate void getRecordsCompletedEventHandler(object sender, getRecordsCompletedEventArgs e);
I chose this example because the synchronous call has a return type and the async does not--at least not in the function call itself. I understand that the getRecordsCompletedEventArgs class has the proper return type, and that that is how I will get the data back from the call. What I can't seem to figure out is how to actually do that.
Let's say that I replace my current call to getRecords with getRecordsAsync:
How do I set up the client to respond when the async call completes? I need to drop the XML into a file using a LINQ procedure I've already written, I need to log the operation's success or failure, and I need to notify the user that the operation completed.
How can I ensure that making the call actually happens asynchronously? I remember reading at one point that simply invoking an asynchronous SOAP method doesn't actually happen asynchronously with regard to the current thread unless you do something else first. Any tips?
Are there any other major considerations that I'm missing? (Such as: "If you forget to do this, it'll blow up your program!")
These are all questions that I haven't been able to find convincingly firm answers to so far. Thank you in advance for any help you all can offer.
You need to handle the getRecordsCompleted event on the proxy which was auto-generated for you, like so:
private void Button_Click(object sender, EventArgs e)
{
var proxy = new WebServiceProxy();
// Tell the proxy object that when the web service
// call completes we want it to invoke our custom
// handler which will process the result for us.
proxy.getRecordsCompleted += this.HandleGetRecordsCompleted;
// Make the async call. The UI thread will not wait for
// the web service call to complete. This method will
// return almost immediately while the web service
// call is happening in the background.
// Think of it as "scheduling" a web service
// call as opposed to actually waiting for it
// to finish before this method can progress.
proxy.getRecordsAsync("USERNAME", new[] { 1, 2, 3, 4 });
this.Button.Enabled = false;
}
/// <summary>
/// Handler for when the web service call returns.
/// </summary>
private void HandleGetRecordsCompleted(object sender, getRecordsCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.ToString());
}
else
{
record[] result = e.Result;
// Run your LINQ code on the result here.
}
this.Button.Enabled = true;
}
If you use an auto-generated method on the proxy which ends with Async, the call will be made asynchronously - and that's it. What it sounds to me that you need to prove is that the call is non-blocking (that is, the UI thread does not have to wait for it to complete), and that's a bit tricky as you can't really inject custom logic into the auto-generated code.
A synchronous call made from a UI thread will block the UI and your application will become unresponsive. If that's not happening and your UI still responds to button clicks, keyboard events etc while the web service is running, you can be sure that the call is non-blocking. Obviously this will be tricky to prove if your web service call returns quickly.
You're not showing any client code so it's hard to say if you're missing anything.
For point 1
I think you are missing something on the code you are showing. Maybe the definition of getRecordsCompleted? It may be of type event I suppose, so you can attach a handler of type getRecordsCompletedEventHandler to your event so you can do something with the result of your asynchronous call.
Let's say your client proxy class name is RecordCleint
RecordClient client = new RecordClient();
//attaching an event handler
client.getRecordsCompleted += onGetRecordsCompleted;
//calling the web service asynchronously
client.getRecordsAsync("username", [ids]);
//definition of onGetRecordsCompleted of type getRecordsCompletedEventHandler
private void onGetRecordsCompleted(object sender, getRecordsCompletedEventArgs e)
{
if(e.Error != null)
{
record[] data = e.Result;
//do something with your data
}
else
{
//handle error
}
}
[Edit]
For point 2
If you are generating your client proxy with svcutil (Visual Studio > add Service reference) you can trust in it :) or you can watch the involved Threads with the Visual Studio Thread window.
For point 3
You might have some Thread synchronization problems, for example if you update some UI components in another Thread than the UI thread where they belong to. So you may need to do some extra work (dispatch).
Windows Forms (BeginInvoke or Dispatcher)
WPF (Dispatcher)

Making a list of subscribers available across calls to a service

So I have created a service that has a callback. Something like this. It works well enough but what I would like to do is have any client that has subscribed be notified that the service was called (and pass some data to the callback function) however this isn't as easy as I thought.
I created two clients, one to call the service and one to listen but although I can see the "listener" (client one) subscribe, on the subsequent call to the service (from client two) the list of subscribers is empty (well except for the calling service, which also subscribes). The first client I started isn't in the list of subscribers. I tried a few tricks to solve this and all of them have failed. Essentially what I tried was a hack to create a static class that kept a static list of subscribers.
a couple of noteworthy requirements. This has to be an http binding so I am using WSDualHttpBinding, I am also using security tokens so the protocol is SOAP. I am wondering if there is something I can do when I set up the endpoint? It seems like that might be a good place? I am not sure though.
So, how do I get a list of subscribers such that I can access any of the subscribed clients whenever my service is called? I am guessing there is a good way to do this hopefully someone can point me in the right direction.
Thanks
i just can say what i have done (i dont know if it is a good style:) but it works).
i create a service with InstanceContextMode.Single
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService
{}
i use a simple dictionary to hold my client "connections" in which the key is the client "ID".
private static Dictionary<GUID, IAdvServiceCallback> Subscribers;
i define a subscribe and unsubscribe methode
public bool Subscribe(GUID key)
{
try
{
if (Subscribers == null)
{
Subscribers = new Dictionary<GUID, IAdvServiceCallback>();
}
lock (Subscribers)
{
IServiceCallback callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
if (!Subscribers.ContainsKey(key))
{
Subscribers.Add(key,callback);
ICommunicationObject obj = (ICommunicationObject)callback;
obj.Closed += SubscribedServiceClosed;
obj.Faulted += SubscribedServiceFaulted;
}
else
{
//log subscriber is registered
}
}
return true;
}
catch (Exception ex)
{
return false;
}
}
public bool UnSubscribe()
{
try
{
if (Subscribers == null)
{
return true;
}
lock (Subscribers)
{
IServiceCallback callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
if (Subscribers.ContainsValue(callback))
{
var row = Subscribers.Where(v => v.Value == callback).FirstOrDefault();
Subscribers.Remove(row.Key);
}
}
return true;
}
catch(Exception ex)
{
return false;
}
}
and now the service can send messages to all subscribers
Subscribers.Values.ToList().ForEach(delegate(IServiceCallback callback)
{
if (((ICommunicationObject) callback).State == CommunicationState.Opened)
{
//send callback
}
else
{
// remove subscriber because channel its not open anymore
}
});

How to Unit Test BeginInvoke on an Action

I am looking for a way to test BeginInvoke on an Action method, since the method runs on a background thread there is no way of knowing when it actually completes or calls callback method. I am looking for a way to keep my test wait until the callback gets called before making assertions.
In the following Presenter class, you can notice that I am invoking PopulateView on background thread which updates the view when data is fetched and I am trying assert the view Properties are correctly initialized.
I am using NUnit and Moq.
public class Presenter
{
private IView _view;
private IService _service;
public Presenter(IView view, IService service)
{
_view = view;
_service = service;
Action action = PopulateView;
action.BeginInvoke(PopulateViewCallback, action);
}
private void PopulateViewCallback(IAsyncResult ar)
{
try
{
Action target = (Action)ar.AsyncState;
target.EndInvoke(ar);
}
catch (Exception ex)
{
Logger.Instance.LogException("Failed to initialize view", ex);
}
}
private void PopulateView()
{
Thread.Sleep(2000); // Fetch data _service.DoSomeThing()
_view.Property1 = "xyz";
}
}
Abstract your code so that you can inject the behavior you want at testing time.
public class MethodInvoker
{
public virtual void InvokeMethod(Action method, Action callback)
{
method.BeginInvoke(callback, method);
}
}
This version is asynchronous. At testing time, you can simply make a blocking version:
public class TestInvoker
{
public IAsyncResult MockResult { get; set; }
public override void InvokeMethod(Action method, Action callback)
{
method();
callback(MockResult);
}
}
Then your code simply changes to this:
// Inject this dependency
Invoker.InvokeMethod(PopulateView, PopulateViewCallback);
At runtime, it's asynchronous. At testing time, it blocks the call.
BeginInvoke() returns an IAsyncResult which you can use to wait.
IAsynchResult ar = action.BeginInvoke(...);
ar.AsyncWaitHandle.WaitOne();
You don't need to check that methods are called instead test the end result - in this case that _view.Propert1 == "xyz".
Because it's an async call you might need to have a loop that Asserts periodically that the value has been set, also a timeout on the test or the check is a must otherwise your test would never fail (just stuck).
You might consider stubbing out the action (PopulateView) in order to skip the Sleep.

Categories