Z
zb
Situation:
Using C#, ASP.Net
Requirement:
1. ASP.net application with virtual hosting service.
2. Requires a service that will run every predefined frequency in
minutes (2, 30, 100, 10000) defined in web.config and do some data
crunching in the database
How am I doing this?
I would prefer to do this (2) as a windows service but since the
service is with hosting solutions virtual hosting windows service is
out of question.
So, the hack I came up with:
For flexibility sake, the service had to be plugin model. The plugin is
derived from IPlugin (I define this) and has the obvious Run, Pause and
Stop and there is a MessageEvent (event) that is used for messaging to
the plugin framwork to log/exception etc.
Design:
In global.asax I create three static methods, one to startService,
launchService and one to stop (stopService)
When Application_start is called (when app is started) a new thread is
started from startService with method launchService which instantiates
the Plugin framework and picks up all plug-in assemblies and runs them
(calls Run method).
Idea behind this design: a new thread so the current execution is not
affected and continues to run while the new thread runs in background
processing the requirement
Plugin model so whenever a background processing is required I can
create a dll and drop it at a location and that is it.
PROBLEM:
The design's problem, if the application is running I can not "hot"
update plugin assembly while application is running since it is locked.
Through research: new AppDomain
Refer to design.
Now, the new thread creates a new appdomain and creates the plugin
framework that in turn does the Assembly.Load plugin assemblies and so
forth.
Problem, stopService can only abort/join the thread.
Question:
a. How can I stop/pause the plugin assemblies in the new thread?
b. I still can not *hot* swap/update plugin assembly? It is locked.
c. Doing appdomain.unload in stopService throws an exception see at the
end number: 1.
d. Will thread.abort /join safe enough to assume that it will call teh
stop?
e. Or is there any way the thread could know that it is being
aborted/joined and it needs to call Stop on all plugins?
f. Does joining/aborting the thread means the new appdomain will be
unloaded/nulled?
Big question:
IS THERE A BETTER WAY this can be implemented?
Thanks in advance.
PS: I will be posting this to csharp group as well, so excuse the cross
posting but the subject is such that it belongs to both groups.
Exception 1:
Type: CannotUnloadAppDomainException
Message: AppDomain can not be unloaded because the thread 1918 can not
be unwound out of it.
Stacktrace:
Server stack trace:
at System.AppDomain.nUnload(Int32 domainInternal, Thread
requestingThread)
at System.UnloadWorker.UnloadWithLock(AppDomain domain, Thread
requestingThread)
at System.UnloadWorker.Unload(AppDomain domain)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(MethodBase
mb, Object[] args, Object server, Int32 methodPtr, Boolean
fExecuteInContext, Object[]& outArgs)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage
msg, Int32 methodPtr, Boolean fExecuteInContext)
Exception rethrown at [0]:
at System.AppDomain.Unload(AppDomain domain)
Using C#, ASP.Net
Requirement:
1. ASP.net application with virtual hosting service.
2. Requires a service that will run every predefined frequency in
minutes (2, 30, 100, 10000) defined in web.config and do some data
crunching in the database
How am I doing this?
I would prefer to do this (2) as a windows service but since the
service is with hosting solutions virtual hosting windows service is
out of question.
So, the hack I came up with:
For flexibility sake, the service had to be plugin model. The plugin is
derived from IPlugin (I define this) and has the obvious Run, Pause and
Stop and there is a MessageEvent (event) that is used for messaging to
the plugin framwork to log/exception etc.
Design:
In global.asax I create three static methods, one to startService,
launchService and one to stop (stopService)
When Application_start is called (when app is started) a new thread is
started from startService with method launchService which instantiates
the Plugin framework and picks up all plug-in assemblies and runs them
(calls Run method).
Idea behind this design: a new thread so the current execution is not
affected and continues to run while the new thread runs in background
processing the requirement
Plugin model so whenever a background processing is required I can
create a dll and drop it at a location and that is it.
PROBLEM:
The design's problem, if the application is running I can not "hot"
update plugin assembly while application is running since it is locked.
Through research: new AppDomain
Refer to design.
Now, the new thread creates a new appdomain and creates the plugin
framework that in turn does the Assembly.Load plugin assemblies and so
forth.
Problem, stopService can only abort/join the thread.
Question:
a. How can I stop/pause the plugin assemblies in the new thread?
b. I still can not *hot* swap/update plugin assembly? It is locked.
c. Doing appdomain.unload in stopService throws an exception see at the
end number: 1.
d. Will thread.abort /join safe enough to assume that it will call teh
stop?
e. Or is there any way the thread could know that it is being
aborted/joined and it needs to call Stop on all plugins?
f. Does joining/aborting the thread means the new appdomain will be
unloaded/nulled?
Big question:
IS THERE A BETTER WAY this can be implemented?
Thanks in advance.
PS: I will be posting this to csharp group as well, so excuse the cross
posting but the subject is such that it belongs to both groups.
Exception 1:
Type: CannotUnloadAppDomainException
Message: AppDomain can not be unloaded because the thread 1918 can not
be unwound out of it.
Stacktrace:
Server stack trace:
at System.AppDomain.nUnload(Int32 domainInternal, Thread
requestingThread)
at System.UnloadWorker.UnloadWithLock(AppDomain domain, Thread
requestingThread)
at System.UnloadWorker.Unload(AppDomain domain)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(MethodBase
mb, Object[] args, Object server, Int32 methodPtr, Boolean
fExecuteInContext, Object[]& outArgs)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage
msg, Int32 methodPtr, Boolean fExecuteInContext)
Exception rethrown at [0]:
at System.AppDomain.Unload(AppDomain domain)