저는 UMLW per UWW per Quartz 작업을 사용하여 StructMap 작업을 다시 한 번 보았습니다. 여기에서 내 솔루션을 공유하기로 결정했습니다.
그래서 나는 HTTP 컨텍스트가있을 때 UoW의 인스턴스를 얻고 http 컨텍스트가 없을 때 (예 : 석영 작업이있을 때와 같이) 스레드마다 UoW의 다른 인스턴스를 얻으려는 경우 StructureMap Hybrid 범위를 사용하려고했습니다 화재). 이와 같이 :
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
http의 UoW가 정상적으로 작동했습니다. 문제는 스레드 당 UoW입니다.
다음과 같은 현상이 발생합니다. quratz 작업이 시작되면 스레드 풀에서 스레드를 당겨 해당 스레드를 사용하여 작업 실행을 시작합니다. 작업이 시작되면 나는 UoW를 요청한다. StructureMap은 UoW를 반환하기 위해 해당 스레드에 대한 로컬 저장소를 찾습니다. 그러나 어떤 스레드도 인스턴스를 생성하지 못하고 스레드의 로컬 저장소 아래에 저장합니다. UoW를 얻은 다음 perfom을 시작하고, Commit, Dispose를 수행합니다.
문제는 이전에 작업을 시작하기 위해 사용했던 스레드 풀에서 스레드를 끌어 와서 (UoW 사용) 문제가 발생합니다. 여기에 UoW를 요청하면 StructureMap은 캐시 (스레드 로컬 저장소)를보고 UoW를 찾아 반환합니다. 그러나 문제는 UoW가 폐기 된 것입니다!
그래서 우리는 스레드 자체가 삭제되지 않고 오래된 캐시 된 삭제 된 UoW를 보유하기 때문에 쿼츠 작업에 스레드 당 UoW를 실제로 사용할 수 없습니다. 기본적으로 스레드의 수명주기가 쿼츠 작업의 수명주기와 일치하지 않습니다. 그래서 석영 작업에 대한 내 자신의 라이프 사이클을 만들었습니다.
public class QuartzLifecycle : ILifecycle
{
public void EjectAll()
{
FindCache().DisposeAndClear();
}
public IObjectCache FindCache()
{
return QuartzContext.Cache;
}
public string Scope { get { return "QuartzLifecycle"; } }
}
가 그럼 난 석영에 대한 HttpContext를 같은 몇 가지 상황에 맞는 클래스를 만들어야합니다
public class HybridHttpQuartzLifecycle : HttpLifecycleBase<HttpContextLifecycle, QuartzLifecycle>
{
public override string Scope { get { return "HybridHttpQuartzLifecycle"; } }
}
가 그럼 난 내 QuartzLifecyle 클래스를 생성 :
먼저 내 자신의 HTTP-석영 하이브리드 라이프 사이클 클래스를 생성 문맥 관련 정보를 보관 유지합니다. 그래서 QuartzContext 클래스를 만들었습니다. 쿼츠 작업이 실행되면 해당 작업의 JobExecutionContext가 QuartzContext에 등록되어야한다. 그런 다음 해당 JobExecutionContext 아래에서 StructureMap 인스턴스의 실제 캐시 (MainObjectCache)가 만들어집니다. 이렇게하면 작업 실행이 끝난 후에도 캐시가 사라지고 캐시에 UoW가 삭제되지 않습니다.
또한 _jobExecutionContext는 ThreadStatic이므로 QuartzContext에서 캐시를 요청할 때 동일한 스레드에 대해 저장된 JobExecutionContext에서 캐시를 반환합니다. 따라서 여러 작업이 동시에 실행될 때 JobExecutionContexts는 개별적으로 저장되며 실행중인 작업마다 별도의 캐시를 갖게됩니다.
public class QuartzContext
{
private static readonly string _cacheKey = "STRUCTUREMAP-INSTANCES";
[ThreadStatic]
private static JobExecutionContext _jobExecutionContext;
protected static void Register(JobExecutionContext jobExecutionContext)
{
_jobExecutionContext = jobExecutionContext;
_jobExecutionContext.Put(_cacheKey, new MainObjectCache());
}
public static IObjectCache Cache
{
get
{
return (IObjectCache)_jobExecutionContext.Get(_cacheKey);
}
}
}
다른 작업에서 파생 된 BaseJobSingleSession이라는 추상 클래스가 있습니다. 이 클래스는 QuartzContext 클래스를 확장한다. 작업이 시작되면 JobExecutionContext를 등록한다는 것을 알 수 있습니다.
abstract class BaseJobSingleSession : QuartzContext, IStatefulJob
{
public override void Execute(JobExecutionContext context)
{
Register(context);
IUnitOfWork unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>();
try
{
unitOfWork.Begin();
// do stuff ....
unitOfWork.Commit();
}
catch (Exception exception)
{
unitOfWork.RollBack();
}
finally
{
unitOfWork.Dispose();
}
}
}
마지막으로 나는 UOW에 대한 라이프 사이클 정의 : (. 내가 StructureMap 소스 코드를 들여다 수명주기와 상황에 맞는 클래스에 대한 아이디어를 얻을 수)
For<IUnitOfWork>().LifecycleIs(new HybridHttpQuartzLifecycle()).Use<UnitOfWork>();
을
공유하세요 귀하의 아이디어, 의견 및 제안 :>
StructureMap으로 석영 IJob을 관리하고 있습니까? –
@Mauricio : 응용 프로그램에서 StructureMap을 사용하고 있습니다. StructeMap으로 석영 작업을 관리한다는 것은 무엇을 의미하는지 모르겠습니다.> – kaptan
은 StructureMap에서 관리하는 Quartz IJob 인스턴스입니까? 다른 말로하면 : 당신은 당신의 직업을 컨테이너에 등록합니까? –