Несколько таймеров с разными интервалами, запись в одну цель
Я пишу службу Windows, которая будет выполнять другую логику импорта данных из разных источников данных, чтобы в конечном итоге записать ее в одну цель, экземпляр MS CRM. Прямо сейчас, единственное, что я думаю, будет проблематично, это запись в CRM-часть. Конкретное чтение данных из другого (иногда одного и того же) источника данных на самом деле не должно быть проблемой (я могу ошибаться в этом...) Так что я нашел способ убедиться, что нет параллельных записей (создание или обновление)) в CRM.
Вот общий дизайн на данный момент:
Что происходит при запуске сервиса:
Timers = new List<System.Timers.Timer>();
CrmTransactionQueue.Lock = new object { }; //Static class. The object for locking purposes...
System.Threading.Thread.Sleep(20000); //for debugging purpose so I can attach to process before everything kicks in...
//retrieve all types that are extending BaseSyncStrategy..
var strategyTypes = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.BaseType == typeof(BaseSyncStrategy));
foreach (Type strategyType in strategyTypes)
{
//create a instance of that type....
var strategy = (BaseSyncStrategy)Activator.CreateInstance(strategyType);
//create a timer for each of these, they will have different intervals...
System.Timers.Timer t = new System.Timers.Timer
{
Interval = strategy.Interval * 1000,
AutoReset = false,
Enabled = true
};
Timers.Add(t);
t.Elapsed += (sender, e) => TimerElapsed(sender, e, strategy);
t.Start();
}
Что происходит, когда интервал таймеров истек:
private void TimerElapsed(object sender, ElapsedEventArgs e, BaseSyncStrategy strategy)
{
//get timer back
var timer = (Timer)sender;
try
{
strategy.Execute();
}
catch (Exception ex)
{
Logger.WriteEntry(EventLogEntryType.Error, $"Error executing strategy {strategy.GetType().Name}: ", ex);
}
timer.Start();
}
И во всех Execute
методы расширения объектов BaseSyncStrategy
Каждый раз, когда я хочу обновить или создать что-то в целевом экземпляре CRM, я делаю это:
XrmServiceContext XrmCtx = new XrmServiceContext();
//....
//code that fetches data from foreign sources and creates CRM entities...
//....
Action<XrmServiceContext> action = (XrmServiceContext ctx) =>
{
//write those created/updated objects
//ctx lets me query entities and write back to CRM...
};
CrmTransactionQueue.Execute(action, XrmCtx);
И простой код, чтобы убедиться (я думаю), что никакие параллельные записи в CRM не произойдут:
public static class CrmTransactionQueue
{
public static object Lock { get; set; }
public static void Execute(Action<XrmServiceContext> transaction, XrmServiceContext Ctx)
{
lock (Lock)
{
transaction.Invoke(Ctx);
}
}
}
Это звуковой дизайн или есть лучший способ сделать это?