Asynchronous queries in a web app, using NHibernate - nhibernate

In a web application, the Session is only available in the current thread.
Does anyone have any tips for executing queries through NHibernate in a new asynchronous thread?
For example, how could I make something like this work:
public void Page_Load()
{
ThreadPool.QueueUserWorkItem(state => FooBarRepository.Save(new FooBar()));
}

You need to have a session context that's smart enough for non web context. But more importantly, the new thread should have it's own session.
You can use something like the following:
private ISession threadSession
{
get
{
if (HttpContext.Current != null)
{
return (ISession)HttpContext.Current.Items["THREAD_SESSION"];
}
return (ISession)AppDomain.CurrentDomain
.GetData("THREAD_SESSION" + Thread.CurrentThread.ManagedThreadId);
}
set
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items["THREAD_SESSION"] = value;
}
else
{
AppDomain.CurrentDomain.SetData("THREAD_SESSION"
+Thread.CurrentThread.ManagedThreadId, value);
}
}
}

Sessions are not thread-safe. IOW you'll run into issues sooner or later if you create a session on one thread and use it from another. Create a new session on your background thread and close it before your background thread finishes.

How about:
public void Page_Load()
{
ThreadPool.QueueUserWorkItem(state => NHibernateSessionFactory.GetSession().Save(new FooBar()));
}

Related

Wrong Thread.CurrentPrincipal in async WCF end-method

I have a WCF service which has its Thread.CurrentPrincipal set in the ServiceConfiguration.ClaimsAuthorizationManager.
When I implement the service asynchronously like this:
public IAsyncResult BeginMethod1(AsyncCallback callback, object state)
{
// Audit log call (uses Thread.CurrentPrincipal)
var task = Task<int>.Factory.StartNew(this.WorkerFunction, state);
return task.ContinueWith(res => callback(task));
}
public string EndMethod1(IAsyncResult ar)
{
// Audit log result (uses Thread.CurrentPrincipal)
return ar.AsyncState as string;
}
private int WorkerFunction(object state)
{
// perform work
}
I find that the Thread.CurrentPrincipal is set to the correct ClaimsPrincipal in the Begin-method and also in the WorkerFunction, but in the End-method it's set to a GenericPrincipal.
I know I can enable ASP.NET compatibility for the service and use HttpContext.Current.User which has the correct principal in all methods, but I'd rather not do this.
Is there a way to force the Thread.CurrentPrincipal to the correct ClaimsPrincipal without turning on ASP.NET compatibility?
Starting with a summary of WCF extension points, you'll see the one that is expressly designed to solve your problem. It is called a CallContextInitializer. Take a look at this article which gives CallContextInitializer sample code.
If you make an ICallContextInitializer extension, you will be given control over both the BeginXXX thread context AND the EndXXX thread context. You are saying that the ClaimsAuthorizationManager has correctly established the user principal in your BeginXXX(...) method. In that case, you then make for yourself a custom ICallContextInitializer which either assigns or records the CurrentPrincipal, depending on whether it is handling your BeginXXX() or your EndXXX(). Something like:
public object BeforeInvoke(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.IClientChannel channel, System.ServiceModel.Channels.Message request){
object principal = null;
if (request.Properties.TryGetValue("userPrincipal", out principal))
{
//If we got here, it means we're about to call the EndXXX(...) method.
Thread.CurrentPrincipal = (IPrincipal)principal;
}
else
{
//If we got here, it means we're about to call the BeginXXX(...) method.
request.Properties["userPrincipal"] = Thread.CurrentPrincipal;
}
...
}
To clarify further, consider two cases. Suppose you implemented both an ICallContextInitializer and an IParameterInspector. Suppose that these hooks are expected to execute with a synchronous WCF service and with an async WCF service (which is your special case).
Below are the sequence of events and the explanation of what is happening:
Synchronous Case
ICallContextInitializer.BeforeInvoke();
IParemeterInspector.BeforeCall();
//...service executes...
IParameterInspector.AfterCall();
ICallContextInitializer.AfterInvoke();
Nothing surprising in the above code. But now look below at what happens with asynchronous service operations...
Asynchronous Case
ICallContextInitializer.BeforeInvoke(); //TryGetValue() fails, so this records the UserPrincipal.
IParameterInspector.BeforeCall();
//...Your BeginXXX() routine now executes...
ICallContextInitializer.AfterInvoke();
//...Now your Task async code executes (or finishes executing)...
ICallContextInitializercut.BeforeInvoke(); //TryGetValue succeeds, so this assigns the UserPrincipal.
//...Your EndXXX() routine now executes...
IParameterInspector.AfterCall();
ICallContextInitializer.AfterInvoke();
As you can see, the CallContextInitializer ensures you have opportunity to initialize values such as your CurrentPrincipal just before the EndXXX() routine runs. It therefore doesn't matter that the EndXXX() routine assuredly is executing on a different thread than did the BeginXXX() routine. And yes, the System.ServiceModel.Channels.Message object which is storing your user principal between Begin/End methods, is preserved and properly transmitted by WCF even though the thread changed.
Overall, this approach allows your EndXXX(IAsyncresult) to execute with the correct IPrincipal, without having to explicitly re-establish the CurrentPrincipal in the EndXXX() routine. And as with any WCF behavior, you can decide if this applies to individual operations, all operations on a contract, or all operations on an endpoint.
Not really the answer to my question, but an alternate approach of implementing the WCF service (in .NET 4.5) that does not exhibit the same issues with Thread.CurrentPrincipal.
public async Task<string> Method1()
{
// Audit log call (uses Thread.CurrentPrincipal)
try
{
return await Task.Factory.StartNew(() => this.WorkerFunction());
}
finally
{
// Audit log result (uses Thread.CurrentPrincipal)
}
}
private string WorkerFunction()
{
// perform work
return string.Empty;
}
The valid approach to this is to create an extension:
public class SLOperationContext : IExtension<OperationContext>
{
private readonly IDictionary<string, object> items;
private static ReaderWriterLockSlim _instanceLock = new ReaderWriterLockSlim();
private SLOperationContext()
{
items = new Dictionary<string, object>();
}
public IDictionary<string, object> Items
{
get { return items; }
}
public static SLOperationContext Current
{
get
{
SLOperationContext context = OperationContext.Current.Extensions.Find<SLOperationContext>();
if (context == null)
{
_instanceLock.EnterWriteLock();
context = new SLOperationContext();
OperationContext.Current.Extensions.Add(context);
_instanceLock.ExitWriteLock();
}
return context;
}
}
public void Attach(OperationContext owner) { }
public void Detach(OperationContext owner) { }
}
Now this extension is used as a container for objects that you want to persist between thread switching as OperationContext.Current will remain the same.
Now you can use this in BeginMethod1 to save current user:
SLOperationContext.Current.Items["Principal"] = OperationContext.Current.ClaimsPrincipal;
And then in EndMethod1 you can get the user by typing:
ClaimsPrincipal principal = SLOperationContext.Current.Items["Principal"];
EDIT (Another approach):
public IAsyncResult BeginMethod1(AsyncCallback callback, object state)
{
var task = Task.Factory.StartNew(this.WorkerFunction, state);
var ec = ExecutionContext.Capture();
return task.ContinueWith(res =>
ExecutionContext.Run(ec, (_) => callback(task), null));
}

When calling a WCF RIA Service method using Invoke, does the return type affect when the Completed callback is executed?

I inherited a Silverlight 5 application. On the server side, it has a DomainContext (service) with a method marked as
[Invoke]
public void DoIt
{
do stuff for 10 seconds here
}
On the client side, it has a ViewModel method containing this:
var q = Context.DoIt(0);
var x=1; var y=2;
q.Completed += (a,b) => DoMore(x,y);
My 2 questions are
1) has DoIt already been activated by the time I attach q.Completed, and
2) does the return type (void) enter into the timing at all?
Now, I know there's another way to call DoIt, namely:
var q = Context.DoIt(0,myCallback);
This leads me to think the two ways of making the call are mutually exclusive.
Although DoIt() is executed on a remote computer, it is best to attach Completed event handler immediately. Otherwise, when the process completes, you might miss out on the callback.
You are correct. The two ways of calling DoIt are mutually exclusive.
If you have complicated logic, you may want to consider using the Bcl Async library. See this blog post.
Using async, your code will look like this:
// Note: you will need the OperationExtensions helper
public async void CallDoItAndDosomething()
{
this.BusyIndicator.IsBusy = true;
await context.DoIt(0).AsTask();
this.BusyIndicator.IsBusy = false;
}
public static class OperationExtensions
{
public static Task<T> AsTask<T>(this T operation)
where T : OperationBase
{
TaskCompletionSource<T> tcs =
new TaskCompletionSource<T>(operation.UserState);
operation.Completed += (sender, e) =>
{
if (operation.HasError && !operation.IsErrorHandled)
{
tcs.TrySetException(operation.Error);
operation.MarkErrorAsHandled();
}
else if (operation.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(operation);
}
};
return tcs.Task;
}
}

Silverlight Dispose pattern with WCF (Async)

I'm a little new to Silverlight, and I want to know how to deal with the Faulted/Disposing of a WCF service.
I'm used to something like this (wcf abort/close pattern) where you call the service in a try/catch (making sure you close or abort). (which works well in a stateless application)
looking into Silverlight, where do we apply the abort/close pattern? as the service call is async and the application is state full.
At the moment the only thing I can think of is some sort of dynamic proxy (using something like Castle DP) accompanied with the ChannelFactoryManager from the n-tier app, about 1/2 way down the page example. where the proxy will ensure there is always an open channel and the ChannelFactoryManager will handle the faults
Because of the asynchronous nature of the Silverlight networking environment I recommend you to build more testable ServiceAgents - long-living singleton wrappers around silverlight's client proxies with callbacks for service methods. You can check real-proxy state (& recreate if needed) before calling service methods or use channel Faulted event. For ex:
public void GetOptionsAsync(Action<GetOptionsCompletedEventArgs> callback)
{
try
{
CheckProxy();
EventHandler<GetOptionsCompletedEventArgs> handler = null;
handler = (sender, args) =>
{
Proxy.GetOptionsCompleted -= handler;
if (args.Error != null)
{
//...
}
if (callback != null)
{
callback(args);
}
};
Proxy.GetOptionsCompleted += handler;
Proxy.GetOptionsAsync();
}
catch (Exception unknownException)
{
//...
throw;
}
}
public override void ResetProxy() //AbortProxy/CloseProxy
{
if (Proxy != null)
{
try
{
Proxy.CloseProxy(); //extension method to handle exception while closing
}
catch (Exception unknownException) //CommunicationObjectFaultedException
{
//...
Proxy.Abort();
}
}
CreateProxy();
}
public override void CheckProxy()
{
if (Proxy == null || (Proxy.State != CommunicationState.Opened && Proxy.State != CommunicationState.Created))
{
ResetProxy();
}
}
public override void CreateProxy() //RecreateProxy
{
Proxy = new WcfClient();
Proxy.InnerChannel.Faulted += OnChannelFaulted;
}
Solution using Castle DP with the ChannelFactoryManager implemented and detailed here:
http://www.codeproject.com/Articles/502121/WCF-in-a-stateful-application-WPF-Silverlight

MMVM Light Using WCF Asynchronously

What is a good practice to implement MMVM with WCF Services? The View model will be communicating with the service. So lets say in a view I have 3-4 data display modules. All this information for the modules is coming from different WCF Service calls.
If I do this synchronously, I have a feeling that the data in the view model will take time to load.
I want to do the calls for all these service methods asynchronously with out waiting for the first call to come back. What is good way of doing this?
I think the best way is to call the Service Asynchronously and then assign value on Complete method, like:
class TestViewModel : ViewModelBase
{
private ObservableCollection<string> data;
public ObservableCollection<string> Data
{
get { return data; }
set
{
if (value == data) return;
data = value;
RaisePropertyChanged("Data");
}
}
public TestViewModel()
{
GetDataClient proxy = new GetDataClient();
System.EventHandler<GetDataCompletedEventArgs> Client_GetDataCompleted = null;
Client_GetDataCompleted = (s, e) =>
{
if (e.Error == null && e.Result != null)
{
Data = new ObservableCollection<SelectionItem<string>>(e.Result));
}
proxy.GetDataCompleted -= Client_GetDataCompleted;
};
proxy.GetDataCompleted += Client_GetDataCompleted;
proxy.GetDataAsync();
}
}

How to Schedule a task for future execution in Task Parallel Library

Is there a way to schedule a Task for execution in the future using the Task Parallel Library?
I realize I could do this with pre-.NET4 methods such as System.Threading.Timer ... however if there is a TPL way to do this I'd rather stay within the design of the framework. I am not able to find one however.
Thank you.
This feature was introduced in the Async CTP, which has now been rolled into .NET 4.5. Doing it as follows does not block the thread, but returns a Task which will execute in the future.
Task<MyType> new_task = Task.Delay(TimeSpan.FromMinutes(5))
.ContinueWith<MyType>( /*...*/ );
(If using the old Async releases, use the static class TaskEx instead of Task)
You can write your own RunDelayed function. This takes a delay and a function to run after the delay completes.
public static Task<T> RunDelayed<T>(int millisecondsDelay, Func<T> func)
{
if(func == null)
{
throw new ArgumentNullException("func");
}
if (millisecondsDelay < 0)
{
throw new ArgumentOutOfRangeException("millisecondsDelay");
}
var taskCompletionSource = new TaskCompletionSource<T>();
var timer = new Timer(self =>
{
((Timer) self).Dispose();
try
{
var result = func();
taskCompletionSource.SetResult(result);
}
catch (Exception exception)
{
taskCompletionSource.SetException(exception);
}
});
timer.Change(millisecondsDelay, millisecondsDelay);
return taskCompletionSource.Task;
}
Use it like this:
public void UseRunDelayed()
{
var task = RunDelayed(500, () => "Hello");
task.ContinueWith(t => Console.WriteLine(t.Result));
}
Set a one-shot timer that, when fired, starts the task. For example, the code below will wait five minutes before starting the task.
TimeSpan TimeToWait = TimeSpan.FromMinutes(5);
Timer t = new Timer((s) =>
{
// start the task here
}, null, TimeToWait, TimeSpan.FromMilliseconds(-1));
The TimeSpan.FromMilliseconds(-1) makes the timer a one-shot rather than a periodic timer.