Guys, hope eveyone is well, but need some advice.
I have a class, and that class has children. Each child is going to connect to a database, calculate some values and return. At the moment this run in sync, so i loop through each child, connect to database, get result and move on to the next one.
This works fine, but i think running the code in async mode would benefit performance.
I seen this on microsoft site http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx describing how to use a ThreadPool to execute async tasks, and the code waits until all the tasks are finished. This sounds exactly like what i want to do, but i understand the Prinical objects etc are not copied over into other threads? I am using asp.net 4.0.
I havent done much async processing, and none where i need to carry the current prinical object.
I have seen that Csla has a backgroundWorker which does pass on the prinicipal values etc. Is there a limit on the number of BackgroundWorkers i can create? How would i wait for all backgroundworkers to complete?
Sorry i this is basic, but thought i would ask here as maybe someone else has had this problem as well
Hi,
I have created a CslaTaskFactory for internal usage (my company) that allows me to setup Tasks / chain Tasks and WaitAll. These tasks will automatically get the principal, UICulture, Culture, ApplicationContext.ClientContext and ApplicationContext.GlobalContext transferred to the background thread.
This has to go into the CSLA assembly itself as the api to set the values is not publicly available.
I will email Rocky to check if this may go into the Csla repository or you can send me a private message and I will share this class with you.
Hi all,
The CslaTaskFactory class will be added to Csla.Threading namespace.
Do you know when this will be added and when it will be released?
Will be added to repository this week.
Not sure when next release is planned (or if we even have a date yet).
Caliburn has an action called a Coroutine. You may be able to use this in the mean time:
Todd
Changes is checked in and ready to be merged into CSLA Trunk.
You can look at the changes here:
https://github.com/MarimerLLC/csla/pull/143
and at the unit tests for usage sample.
I plan to do a beta release of this new code (along with support for Android with all 4.5 features) this weekend or early next week.
Can someone please send me the link to download the installer for the latest version as i havent got Visual Studio 2012, and really need this code please.
Hi,
You can use NuGet in VS2010 too - just remember to check PreRelease in your search.
Right i have downloaded NuGet in VS2010, got the Csla dll's etc that i need. perfect.
But this code does not pass my userPrincipal. Instead it has a generic principal populated, and a FormsIdentity in Csla.ApplicationContext.User.Identity, which is not right and causing me errors?
Is this code right to use Tasks? I have never used them before
----------------------------------
Dim lReportId As Integer
Dim lTasks(lData.Count - 1) As System.Threading.Tasks.Task
Dim lTaskScheduler As New Csla.Threading.CslaTaskScheduler
Dim lTaskFactory As New System.Threading.Tasks.TaskFactory(lTaskScheduler)
lIndex = 0
' loop through and do work
While lIndex < lData.Count
lReportId = lData.Keys(lIndex)
' add item to lDoneEvents
lTasks(lIndex) = New System.Threading.Tasks.Task(Function(pReportId As Integer)
Dim lReport As IBaseReport = Report.GetReportByID(pReportId)
lData(pReportId) = lReport
Return True
End Function, lReportId)
lTasks(lIndex).Start(lTaskScheduler)
lIndex += 1
End While
System.Threading.Tasks.Task.WaitAll(lTasks, New TimeSpan(0, 0, 30).TotalMilliseconds)
Guys, i believe the code i wrote above is right. I dont know what the problem is but it seems to be linked to vs 2010 / .NET 4.0?
I have managed to get a copy of VS 2012, and if i create a basic website with the code above, it works (using .NET 4.5 and .NET 4.0). The prinicipal is passed to within the task.
If i create a basic website in vs 2010, same code, the principal is not passed and you get a genericprinicipal/formsidentity in the task code.
Would love some more help with this please, maybe its a bug? Or maybe i need to do something particular because i am using vs2010 / .net 4.0.
Any help would be much much much appreicated
Here is the test code i created and put on the default page
Public Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Csla.ApplicationContext.User = Nothing
Csla.ApplicationContext.User = New myPrincipal
Dim lIndex As Integer = 0
Dim lTasks(0) As System.Threading.Tasks.Task
Dim lTaskScheduler As New Csla.Threading.CslaTaskScheduler
Dim lTaskFactory As New System.Threading.Tasks.TaskFactory(lTaskScheduler)
' loop through and do work
While lIndex < 1
' add item to lDoneEvents
lTasks(lIndex) = New System.Threading.Tasks.Task(Function(pReportId As Integer)
Dim a As String = pReportId.ToString
Dim b As myPrincipal = TryCast(Csla.ApplicationContext.User, myPrincipal)
Return True
End Function, 123)
lTasks(lIndex).Start(lTaskScheduler)
lIndex += 1
End While
System.Threading.Tasks.Task.WaitAll(lTasks, New TimeSpan(0, 0, 30).TotalMilliseconds)
Csla.ApplicationContext.User = Nothing
End Sub
End Class
Public Class myPrincipal
Implements System.Security.Principal.IPrincipal
Public ReadOnly Property Identity As System.Security.Principal.IIdentity Implements System.Security.Principal.IPrincipal.Identity
Get
Return New myIdentity
End Get
End Property
Public Function IsInRole(role As String) As Boolean Implements System.Security.Principal.IPrincipal.IsInRole
Return True
End Function
End Class
Public Class myIdentity
Implements System.Security.Principal.IIdentity
Public ReadOnly Property AuthenticationType As String Implements System.Security.Principal.IIdentity.AuthenticationType
Get
Return "MINE"
End Get
End Property
Public ReadOnly Property IsAuthenticated As Boolean Implements System.Security.Principal.IIdentity.IsAuthenticated
Get
Return True
End Get
End Property
Public ReadOnly Property Name As String Implements System.Security.Principal.IIdentity.Name
Get
Return "MY NAME IS HERE"
End Get
End Property
End Class
Hi,
In your VS2010 solution - do you have both Csla.Web.dll and Csla.Web.Mvc,dll in your bin.folder?
You must have Csla.Web.dll in your bin folder for ApplicationContext to use the Csla.Web.ApplcationContextManager that stores/retrieves the Principal object from HttpContext.Current.User
When you move on to the background thread the HttpContext.Current will be null and Csla.ApplicationContext will revert to use the "default" Csla.ApplicationContext.ApplicationContextManager that stores/retrieves the Principal object from Thread.CurrentPrincipal
I do not have VS2010 installed on my dev computer so unfortunately I am unable to dig more into it right now if it is a VS2010 issue.
Hi,
In your VS2010 solution - do you have both Csla.Web.dll and Csla.Web.Mvc,dll in your bin.folder?
You must have Csla.Web.dll in your bin folder for ApplicationContext to use the Csla.Web.ApplcationContextManager that stores/retrieves the Principal object from HttpContext.Current.User
When you move on to the background thread the HttpContext.Current will be null and Csla.ApplicationContext will revert to use the "default" Csla.ApplicationContext.ApplicationContextManager that stores/retrieves the Principal object from Thread.CurrentPrincipal
I do not have VS2010 installed on my dev computer so unfortunately I am unable to dig more into it right now if it is a VS2010 issue.
In my VS2010 project I have Csla.dll and Csla.Web.dll referenced in my web project. I do not have Csla.Web.Mvc.dll referenced.
I have just added a new web application using VS2012, and added Csla.dll only. This works.
I have then added a new web application using VS 2010 and added Csla.dll only, and this seems to work.
So....i then create a new web application in VS 2010 AND VS 2012 and add Csla.ASP.NET, which includes Csla.dll and Csla.Web.dll, then it doesnt work.
It appears that Csla.Web.dll seems to be the problem....??
Hi,
Then it seems that HttpContext.Current is part of the problem here.
Any chance this can be looked at, and let me know the bug. Love the new feature, just need csla.web too :)
Thanks for the help so far
I can confirm that System.Web.HttpContext.Current.User is nothing upon entering the task. I am guessing that this should contain the custom identity?
Yes,
assuming that you have a web application - you should store the "userprincipal" in HttpContext.Current.User
This is the containter that Csla.Web.ApplicationContextManager stores userprincipal and when you create the CslaTaskFactory object it makes a "snapshot" of the variables to pass on to the tasks for context values,
In our web app, we store the user in Csla.ApplicationContext.User and also hold it in Session.
Then in the global.asax file we assign Csla.ApplicationContext.User equal to the Session variable.
I presume that setting Csla.ApplicationContext.User in a web app, sets HttpContext.Current.user automatically?
Please make sure you are not hit with this in ASP.NET MVC 4
See this post: http://forums.lhotka.net/forums/p/11830/55521.aspx#55521
I have tried this and still get the same error...
Any news on when the CslaFactory is going to be avilable for download via the website? Have all the issues been solved yet?
Code is available here:
https://github.com/MarimerLLC/csla/tree/master/Source/Csla/Threading
As for issues with VS2010 my problem is that I no longer have a dev-computer with VS2010 and .NET 4.0.
So any help to identify/resolve issues is appreciated.
https://github.com/MarimerLLC/csla/tree/master/Source/Csla/Threading
As for issues with VS2010 my problem is that I no longer have a dev-computer with VS2010 and .NET 4.0.
So any help to identify/resolve issues is appreciated.
Hey Jonny, I think that since the new background thread doesn't get an HttpContext the normal thread rules apply. The CslaTaskFactory should probably set the newly created thread's principal before starting to run it. That should allow the impersonation to work correctly.
Hey Jonny, I think that since the new background thread doesn't get an HttpContext the normal thread rules apply. The CslaTaskFactory should probably set the newly created thread's principal before starting to run it. That should allow the impersonation to work correctly.
Yes that is probably why my web version doesnt work, but it works via windows forms...
Any know the code to recreate/copy the principal to the newly created thread? I am happy to write the code into my version of csla and test it
@Andy: That's exactly what the CslaTaskFactory tries to do.
When CslaTaskFactory is created it stores a "snapshot" of:
And sets these values values on the new thread before calling the actual task.
So all the logic of HttpContext or not is handled by Csla.ApplicationContext (and there is 3 stereotypes of ApplicationContext in CSLA).
(and there is 3 stereotypes of ApplicationContext in CSLA).
And what does this mean? For me while using this via webpage current.httpcontext.user is nothing
It means that CSLA has 3 implementations of Csla.Core.IContextManager: a default ApplicationContextManager and 2 specialiced:
Default: Csla.ApplicationContext.ApplicationContextManager
Xaml: Csla.Xaml.ApplicationContextManager - specialized for Xaml applications with knowledge and use of System.Windows.Application.Current
Web: Csla.Web.ApplicationContextManager - specialized for Web applications with knowledge and use of System.Web.HttpContext.Current
The key issue for your code (I believe) is to find out why HttpContext.Current.User is null before you enter the async code. It should have a value.
The right word isn't 'stereotype', it is 'provider. Csla.ApplicationContext uses a provider model to load a different implementation depending on your application.
There are three standard providers (and you can create your own).
Also, things like HttpContext and System.Threading.Thread are owned by Microsoft, and we don't manage those values except in very limited circumstances. As a result, when writing code within a CSLA app you are best off using Csla.ApplicationContext instead of things like HttpContext, because HttpContext follows its own set of rules, and ApplicationContext provides some extra behaviors that are often useful. Not least of these is that ApplicationContext works in ASP.NET and _outside_ of ASP.NET (including on background threads).
The default provider stores its data in something called thread local storage, and so makes the values available to all code running on a thread. This is appropriate when not in ASP.NET or WPF.
The ASP.NET web provider stores its data in HttpContext, so as long as Microsoft flows HttpContext the values are available. We don't change how HttpContext works, we just use it for data storage.
The WPF provider (also used in SL and WinRT) stores its data in static fields. This isn't entirely ideal, but does make the values available even as WPF tries really hard to blank them, and also because SL/WinRT don't have the concept of thread local storage or HttpContext...
In a typical ASP.NET Web Forms or MVC app you'll be using the ASP.NET provider, which (on the primary thread) stores its values in HttpContext. But ASP.NET doesn't flow HttpContext onto background threads, and we don't alter that behavior because Microsoft owns HttpContext and it would be pretty dumb to try and alter their implementation. What Jonny has done is to provide some helpers in Csla.Threading that allow you to create or call background threads/tasks such that ApplicationContext flows the values from the primary thread onto the background thread.
Copyright (c) Marimer LLC