我不熟悉后台工作(通常在Task用法方面),并且对自己的实现方式有疑问。
(注意:如果您认为它太长了,请通过评论告知我,我将其缩短)
假设WCF服务返回货币汇率:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class RatesServiceSvc : IGetRatesService
RatesServiceSvc
取决于IRatesService
(单音)。IRatesService
取决于IRatesQueueDispatcher
。
拥有ratesCache
字典。并在其构造函数中调用RunDispatcher(_ratesQueue, _dispatcherCancellationTokenSource);
IRatesService
的内部实现是这样的:该服务实例化一个第三方队列,该队列从网络获取当前费率并将其作为事件推送到队列(无休止地)。为了获取事件,我需要调用运行backgroun循环的IRatesQueueDispatcher.Run(...)
:
IRatesService
实现:
private void RunDispatcher(Queue queue, CancellationTokenSource dispatcherCancellationTokenSource)
{
Task<TaskCompletionCause> dispatcher = Task.Run(() => _queueDispatcher.Run(queue, dispatcherCancellationTokenSource.Token));
dispatcher.ContinueWith((dispatcherTask) =>
{
HandleRunningTaskTermination(dispatcherTask.Result);
});
}
IRatesQueueDispatcher.Run()实现:
while (!cancellationToken.IsCancellationRequested && IsRatesQueueOk(eventsCount))
{
eventsCount = ratesQueueToDispatch.Dispatch();
if (eventsCount < 0)
{
Thread.Sleep(_sleepTimeWhenReutersQueueEmpty);
}
}
queue.Dispach()
调用导致调用(在同一线程中)EventClient.ProcessEvent(event)
(在初始化阶段注册)的实现。从插入rateCache
的事件中获取的数据(在本例中为ConcurrentDictionary
)
应用程序需要:
问题:
我用Task.Run(...).ContinueWith(...)
运行背景的解决方案可以吗?我在一些地方读过有关“失火和遗忘”的危险(here
和here),我也知道.NET 4.5.2建议HostingEnvironment.QueueBackgroundWorkItem
但是我不确定这是否适合我。因为:
我需要从内部原因了解工作人员是否失败。
在我看来,HostingEnvironment.QueueBackgroundWorkItem
的主要目的是保证在application_end
之前完成正在运行的任务。就我的需求而言,在应用程序结束时运行后台工作没有任何意义,反之亦然-如果后台失败,则没有该应用程序就没有运行的意义。因此,我实现了HandleRunningTaskTermination()
以通过调用System.Web.HttpRuntime.UnloadAppDomain();
来回收应用程序。
毕竟,我担心自己的实现,并且正在寻找更好的解决方案。有更好的吗?