Programming synchronous web service calls in flex - apache-flex

Web service calls are asynchronous in flex, but I wanted to wrap a web service call in a class to provide synchronous encapsulation. Something like the below - the user could call getMyMethodResult and get the result returned by the web service. I expected the thread that recieved the soap response would populate the variable _result and mean that getMyMethod would, after a time, find _result is not longer null. But it doesn't! Can anyone explain why this does not work?
public class myClass
{
private var _result:Object;
public function myClass()
{
//create a web service object
...
// Add listener
_service.addMyMethodListener(myMethodListener);
}
public function getMyMethodResult()
{
_service.myMethod();
while (_result == null)
{
// count a variable or something (unimportant)
}
return _result;
}
private function myMethodListener(event:Event):void
{
_result = event.result;
}
}

There's is absolutely no support for that. The event loop runs between frames and as long as you block the execution with your (infinite) loop, your myMethodListener function will not be called. Anyway, this would be a terrible idea since the absence of threading in the Flash Player will cause your UI to freeze while you wait for your service to return. You should just drop that idea.

Related

Re-instantiate a singleton with Prism in Xamarin Forms

How can I dispose and re-instantiate a singleton with Prism/DryIoC in Xamarin Forms?
I'm working with Azure Mobile Apps for offline data. Occasionally, I need to delete the local sqlite database and re-initialize it. Unfortunately the MobileServiceClient occasionally holds the db connection open and there's no method exposed to close it. The suggested solution (https://github.com/Azure/azure-mobile-apps-net-client/issues/379) is to dispose of MobileServiceClient. Only problem is that is registered with DryIoC as a singleton.
I'm not overly familiar with DryIoC, or Prism and Forms for that matter... But for the life of me, I can't see a way to do this.
I did cook up a pretty elaborate scheme that almost worked.
In my ViewModel method, when I needed the db freed up, I fired off an event -
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(false);
Then in App.xaml.cs, I wired up a listener and a handler like so -
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Subscribe(OnRegisterDatabaseEventPublished);
private void OnRegisterDatabaseEventPublished()
{
Container.GetContainer().Unregister<IAppMobileClient>();
Container.GetContainer().Unregister<IMobileServiceClient>();
Container.GetContainer().Register<IMobileServiceClient, AppMobileClient>(new SingletonReuse());
Container.GetContainer().Register<IAppMobileClient, AppMobileClient>(new SingletonReuse());
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
}
Lastly, back in the ViewModel constructor, I had a final listener that handled the event coming back from App.xaml and finished processing.
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Subscribe(OnRegisterDatabaseCompletedEventPublished);
So the amazing thing is that this worked. The database was able to be deleted and all was good. But then I navigated to a different page and BOOM. DryIoC said it couldn't wire up the ViewModel for that page. I assume the unregister/register jacked up DryIoC for all injection... So how can I accomplish what needs to be done?
FINAL SOLUTION
Thanks so much to dadhi for taking the time to help. You are certainly a class act and I'm now considering using DryIoC elsewhere.
For anyone who stumbles on this, I'm posting the final solution below. I'll be as verbose as I can to avoid any confusion.
First, in my App.xaml.cs, I added a method for registering my database.
public void RegisterDatabase(IContainer container)
{
container.RegisterMany<AppMobileClient>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true),
ifAlreadyRegistered: IfAlreadyRegistered.Replace,
serviceTypeCondition: type =>
type == typeof(IMobileServiceClient) || type == typeof(IAppMobileClient));
}
I simply add a call to that method in RegisterTypes in place of registering the types in there directly.
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.GetContainer().Rules.WithoutEagerCachingSingletonForFasterAccess();
...
RegisterDatabase(containerRegistry.GetContainer());
...
}
Note also the added rule for eager caching, per dadhi.
Later on when I need to release the database in the ViewModel... I kick things off by resetting my local db variable and sending an event to App.xaml.cs
_client = null;
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(true);
In App.xaml.cs, I have subscribed to that event and tied it to the following method.
private void OnRegisterDatabaseEventPublished()
{
RegisterDatabase(Container.GetContainer());
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
}
Here I just call RegisterMany again, exactly the same as I do when the app starts up. No need to unregister anything. With the setup and ifAlreadyRegistered arguments (thanks, dadhi!), DryIoC allows the object to be replaced. Then I raise an event back to the VM letting it know the database has been released.
Finally, back in the ViewModel, I'm listening for the completed event. The handler for that event updates the local copy of the object like so.
_client = ((PrismApplication)App.Current).Container.Resolve<IAppMobileClient>();
And then I can work with the new object, as needed. This is key. Without setting _client to null above and resolving it again here, I actually ended up with 2 copies of the object and calls to methods were being hit 2x.
Hope that helps someone else looking to release their Azure Mobile Apps database!
I am not sure how exactly XF handles these things.
But in DryIoc in order for service to be fully deleted or replaced it need to be registered with setup: Setup.With(asResolutionCall: true). Read here for more details: https://bitbucket.org/dadhi/dryioc/wiki/UnregisterAndResolutionCache#markdown-header-unregister-and-resolution-cache
Update
Here are two options and considerations that work in pure DryIoc and may not work XF. But it probably may help with solution.
public class Foo
{
public IBar Bar { get; private set; }
public Foo(IBar bar) { Bar = bar; }
}
public interface IBar {}
public class Bar : IBar {}
public class Bar2 : IBar { }
[Test]
public void Replace_singleton_dependency_with_asResolutionCall()
{
var c = new Container(rules => rules.WithoutEagerCachingSingletonForFasterAccess());
c.Register<Foo>();
//c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
// cause the consumer singleton should be replaced too
c.Register<IBar, Bar>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true)); // required
var foo = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar>(foo.Bar);
c.Register<IBar, Bar2>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true), // required
ifAlreadyRegistered: IfAlreadyRegistered.Replace); // required
var foo2 = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar2>(foo2.Bar);
}
[Test]
public void Replace_singleton_dependency_with_UseInstance()
{
var c = new Container();
c.Register<Foo>();
//c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
// cause the consumer singleton should be replaced too
c.UseInstance<IBar>(new Bar());
var foo = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar>(foo.Bar);
c.UseInstance<IBar>(new Bar2());
var foo2 = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar2>(foo2.Bar);
}

Is it possible to create an async inteceptor using Castle.DynamicProxy?

We basically have a class that looks like this below that is using the Castle.DynamicProxy for Interception.
using System;
using System.Collections.Concurrent;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Castle.DynamicProxy;
namespace SaaS.Core.IoC
{
public abstract class AsyncInterceptor : IInterceptor
{
private readonly ILog _logger;
private readonly ConcurrentDictionary<Type, Func<Task, IInvocation, Task>> wrapperCreators =
new ConcurrentDictionary<Type, Func<Task, IInvocation, Task>>();
protected AsyncInterceptor(ILog logger)
{
_logger = logger;
}
void IInterceptor.Intercept(IInvocation invocation)
{
if (!typeof(Task).IsAssignableFrom(invocation.Method.ReturnType))
{
InterceptSync(invocation);
return;
}
try
{
CheckCurrentSyncronizationContext();
var method = invocation.Method;
if ((method != null) && typeof(Task).IsAssignableFrom(method.ReturnType))
{
var taskWrapper = GetWrapperCreator(method.ReturnType);
Task.Factory.StartNew(
async () => { await InterceptAsync(invocation, taskWrapper).ConfigureAwait(true); }
, // this will use current synchronization context
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.FromCurrentSynchronizationContext()).Wait();
}
}
catch (Exception ex)
{
//this is not really burring the exception
//excepiton is going back in the invocation.ReturnValue which
//is a Task that failed. with the same excpetion
//as ex.
}
}
....
Initially this code was:
Task.Run(async () => { await InterceptAsync(invocation, taskWrapper)).Wait()
But we were losing HttpContext after any call to this, so we had to switch it to:
Task.Factory.StartNew
So we could pass in the TaskScheduler.FromCurrentSynchronizationContext()
All of this is bad because we are really just swapping one thread for another thread. I would really love to change the signature of
void IInterceptor.Intercept(IInvocation invocation)
to
async Task IInterceptor.Intercept(IInvocation invocation)
And get rid of the Task.Run or Task.Factory and just make it:
await InterceptAsync(invocation, taskWrapper);
The problem is Castle.DynamicProxy IInterecptor won't allow this. I really want do an await in the Intercept. I could do .Result but then what is the point of the async call I am calling? Without being able to do the await I lose out of the benefit of it being able to yield this threads execution. I am not stuck with Castle Windsor for their DynamicProxy so I am looking for another way to do this. We have looked into Unity, but I don't want to replace our entire AutoFac implementation.
Any help would be appreciated.
All of this is bad because we are really just swapping one thread for another thread.
True. Also because the StartNew version isn't actually waiting for the method to complete; it will only wait until the first await. But if you add an Unwrap() to make it wait for the complete method, then I strongly suspect you'll end up with a deadlock.
The problem is Castle.DynamicProxy IInterecptor won't allow this.
IInterceptor does have a design limitation that it must proceed synchronously. So this limits your interception capabilities: you can inject synchronous code before or after the asynchronous method, and asynchronous code after the asynchronous method. There's no way to inject asynchronous code before the asynchronous method. It's just a limitation of DynamicProxy, one that would be extremely painful to correct (as in, break all existing user code).
To do the kinds of injection that is supported, you have to change your thinking a bit. One of the valid mental models of async is that a Task returned from a method represents the execution of that method. So, to append code to that method, you would call the method directly and then replace the task return value with an augmented one.
So, something like this (for return types of Task):
protected abstract void PreIntercept(); // must be sync
protected abstract Task PostInterceptAsync(); // may be sync or async
// This method will complete when PostInterceptAsync completes.
private async Task InterceptAsync(Task originalTask)
{
// Asynchronously wait for the original task to complete
await originalTask;
// Asynchronous post-execution
await PostInterceptAsync();
}
public void Intercept(IInvocation invocation)
{
// Run the pre-interception code.
PreIntercept();
// *Start* the intercepted asynchronous method.
invocation.Proceed();
// Replace the return value so that it only completes when the post-interception code is complete.
invocation.ReturnValue = InterceptAsync((Task)invocation.ReturnValue);
}
Note that the PreIntercept, the intercepted method, and PostInterceptAsync are all run in the original (ASP.NET) context.
P.S. A quick Google search for async DynamicProxy resulted in this. I don't have any idea how stable it is, though.

synchronously invoke client side method with SignalR

SignalR does not have the ability to have client methods which returns a value. So I am trying to create a helper class to make this possible.
So this is what I am trying to do:
Server side: Call client method and provide unique request id Client(clientId).GetValue(requestId)
Server side: Save requestId and wait for answer using ManualResetEvent
Client side: Inside void GetValue(Guid requestId) call server method hubProxy.Invoke("GetValueFinished", requestId, 10)
Server side: find waiting method by requestId => set return value => set signal
Server side: Method not longer waiting vor ManualResetEvent and returns retrieved value.
I am able to get it work unfortunately. Here is my code:
public static class MethodHandler
{
private static ConcurrentDictionary<Guid, ReturnWaiter> runningMethodWaiters = new ConcurrentDictionary<Guid,ReturnWaiter>();
public static TResult GetValue<TResult>(Action<Guid> requestValue)
{
Guid key = Guid.NewGuid();
ReturnWaiter returnWaiter = new ReturnWaiter(key);
runningMethodWaiters.TryAdd(key, returnWaiter);
requestValue.Invoke(key);
returnWaiter.Signal.WaitOne();
return (TResult)returnWaiter.Value;
}
public static void GetValueResult(Guid key, object value)
{
ReturnWaiter waiter;
if (runningMethodWaiters.TryRemove(key, out waiter))
{
waiter.Value = value;
}
}
}
internal class ReturnWaiter
{
private ManualResetEvent _signal = new ManualResetEvent(false);
public ManualResetEvent Signal { get { return _signal; } }
public Guid Key {get; private set;}
public ReturnWaiter(Guid key)
{
Key = key;
}
private object _value;
public object Value
{
get { return _value; }
set
{
_value = value;
Signal.Set();
}
}
}
Using this MethodHandler class I need to have two method server side:
public int GetValue(string clientId)
{
return MethodHandler.GetValue<int>(key => Clients(clientId).Client.GetValue(key));
}
public void GetValueResult(Guid key, object value)
{
MethodHandler.GetValueResult(key, value);
}
Client side implementation is like this:
// Method registration
_hubProxy.On("GetValue", new Action<Guid>(GetValue));
public void GetValue(Guid requestId)
{
int result = 10;
_hubConnection.Invoke("GetValueResult", requestId, result);
}
PROBLEM:
if I call server side GetValue("clientid"). The client method will not be invoked. If I comment out returnWaiter.Signal.WaitOne();, client side GetValue is called and server side GetValueResult is called. But of course this time the method has already returned.
I thought is has to do with the ManualResetEvent but even using while(!returnWaiter.HasValue) Thread.Sleep(100); will not fix this issue.
Any ideas how to fix this issue?
Thanks in advance!
First, I think that, rather than asking for help in how to make it synchronous, it would be best if you just told us what it is you're trying to do so we could suggest a proper approach to do it.
You don't show your MethodHandler::Retrieve method, but I can guess pretty much what it looks like and it's not even the real problem. I have to tell you in the nicest possible way that this is a really bad idea. It will simply never scale. This would only work with a single SignalR server instance because you're relying on machine specific resources (e.g. kernel objects behind the ManualResetEvent) to provide the blocking. Maybe you don't need to scale beyond one server to meet your requirements, but this still a terrible waste of resources even on a single server.
You're actually on the right track with the client calling back with the requestId as a correlating identifier. Why can't you use that correlation to resume logical execution of whatever process you are in the middle of on the server side? That way no resources are held around while waiting for the message to be delivered to the client, processed and then the follow up message, GetValueResult in your sample, to be sent back a the server instance.
Problem solved:
The problem only occured in Hub.OnConnected and Hub.OnDisconnected. I don't have an exact explanation why, but probably these methods must be able to finish before it will handle your method call to the client.
So I changed code:
public override Task OnConnected()
{
// NOT WORKING
Debug.Print(MethodHandler.GetValue<int>(key => Clients(Context.ConnectionId).Client.GetValue(key)));
// WORKING
new Thread(() => Debug.Print(MethodHandler.GetValue<int>(key => Clients(Context.ConnectionId).Client.GetValue(key)))).Start();
return base.OnConnected();
}

How do I properly execute an Async Method in ASP.net MVC?

How do I execute an asynchronous method from within a controller method and return an HttpStatusCodeResult(200), without the async delegate prematurely terminating its execution?
I am working on an asp.net application and one of my action my home controller takes long time to run(10-30 sec). I want to return an HttpStatusCodeResult(200) and keep running my function. The functoin need not to return anything, but still it's not really a case of fire and forget since I return a response to the server right away with HttpStatusCodeResult.
I tried using delegates, but it seems once I return the status code from the action, the delegate stops executing. Another option is to create a windows service but that would be like using a bazooka to kill a fly. I get very few requests so resources and performance is not an issue in my case. I heard ThreadPool.QueueUserWorkItem is an option, but which is most suitable for my case?
Create a static class that manages this long-running operation. This class will be responsible for creating threads to perform the task and also provides a way to check up on the status of any ongoing operations (i.e. if it's still in progress or has finished, and if so, what the result is).
Your MVC Controller method then uses this class to do the work and present status information or the completed processed data to the user.
Something like this:
public ActionResult GetSomething(String id) {
TaskResult result = TaskClass.GetStatus( id );
if( result == null ) { // the task has not been run, so start it up
TaskClass.StartNew( id );
return new View("PleaseWait");
} else if( !result.IsFinished ) {
return new View("PleaseWait");
} else {
return View("Results", result);
}
}
public static class TaskClass {
private static Dictionary<String,TaskResult> _tasks;
public static TaskResult GetStatus(String id) {
// TODO: Make this code thread-safe
if( _tasks.ContainsKey(id) ) return _tasks[id];
return null;
}
public static void Start(String id) {
_tasks.Add( id, new TaskResult("Working") );
Thread thread = new Thread( SomeExpensiveOperation );
thread.Start( id );
}
}
At the end of SomeExpensiveOperation there would be code that marks the TaskResult as finished.

ASP.net how to long polling with PokeIn?

I want to make a service that notify the user in case there are some new messages sent to him. Thus I want to use some Comet framework that provide the server push ability. So I have looked into PokeIn.
Just wondering a thing. I have checked on the samples that they have on the website. None of them look into the database to retrieve new entries if there are some. But it is just a matter of modification to it I guess.
One of the sample implement this long polling by using a sleep on the server side. So if I use the same approach I can check the database, if there are any new entries, every 5 seconds. However this approach doesn't seem to be much different from when using polling on the client side with javascript.
This part is from a sample. As can be seen they put a sleep there for to update current time for everybody.
static void UpdateClients()
{
while (true)
{
//.. code to check database
if (CometWorker.ActiveClientCount > 0)
{
CometWorker.SendToAll(JSON.Method("UpdateTime", DateTime.Now));
}
Thread.Sleep(500);
}
}
So I wonder is this how I should implement the message notifier? It seems that the above approach is still going to push a huge load demand on the server side. The message notifier is intend to work same way as the one found Facebook.
You shouldn't implement this way, that sample is only implemented like that because the keep PokeIn related part is clear. You should implement SQL part as mentioned http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
in order to track changes on database.
So, when you have something to send, call one of the PokeIn methods for the client side delivery. I don't know, how much your application is time critical because in addition to reverse ajax, PokeIn's internal websocket feature is very easy to activate and delivers messages to client quite fast.
You can do this with database as #Zuuum said, but I implemented it in a different way.
I'm using ASP.NET MVC with PokeIn and EF in a Windows Azure environment:
I have domain events similar to this approach: Strengthening your domain: Domain Events
When someone invokes an action, that's a Unit of Work
If that UOW succeeds then I raise a domain event (e.g. ChatMessageSent)
I have subscribers for these domain events so they can receive the event and forward the message to the PokeIn listeners
I use this pattern for all my real-time needs on my game site (making moves, actions etc in a game), I don't want to advertise it here, you can find it through me if you want.
I always use this pattern as a duplex communication solution so everybody gets their update via PokeIn, even the user who invoked the action so every client will behave the same. So when someone calls an action it won't return anything except the success signal.
The next examples are won't work because they are only snippets to demonstrate the flow
Here is an action snippet from my code:
[HttpPost]
[UnitOfWork]
[RestrictToAjax]
[ValidateAntiForgeryToken]
public JsonResult Post(SendMessageViewModel msg)
{
if (ModelState.IsValid)
{
var chatMessage = new ChatMessage
{
ContainerType = msg.ContainerType,
ContainerID = msg.ContainerID,
Message = _xssEncoder.Encode(msg.Message),
User = _profileService.CurrentUser
};
_chatRepository.AddMessage(chatMessage);
OnSuccessfulUoW = () => EventBroker.Current.Send(this, new ChatMessageSentPayload(chatMessage));
}
return Json(Constants.AjaxOk);
}
And the (simplified) EventBroker implementation:
public class UnityEventBroker : EventBroker
{
private readonly IUnityContainer _container;
public UnityEventBroker(IUnityContainer container)
{
_container = container;
}
public override void Send<TPayload>(object sender, TPayload payload)
{
var subscribers = _container.ResolveAll<IEventSubscriber<TPayload>>();
if (subscribers == null) return;
foreach (var subscriber in subscribers)
{
subscriber.Receive(sender, payload);
}
}
}
And the even more simplified subscriber:
public class ChatMessageSentSubscriber : IEventSubscriber<ChatMessageSentPayload>
{
public void Receive(object sender, ChatMessageSentPayload payload)
{
var message = payload.Message;
var content = SiteContent.Global;
var clients = Client.GetClients(c => c.ContentID == message.ContainerID && c.Content == content)
.Select(c => c.ClientID)
.ToArray();
var dto = ObjectMapper.Current.Map<ChatMessage, ChatMessageSentDto>(message);
var json = PokeIn.JSON.Method("pokein", dto);
CometWorker.SendToClients(clients, json);
}
}

Resources