Quartz.NET & amp; WPF [дубликат]

Раньше я думал, что создание объектов во время выполнения будет лучшим подходом. Теперь я менее уверен, так как вы теряете некоторые полезные функции, хотя это может стоить того, что было бы просто для предотвращения путаницы новичков. Недостатками этого являются:

1. Производительность

def foo(arg=something_expensive_to_compute())):
    ...

Если используется оценка времени вызова, тогда дорогая функция вызывается каждый раз, когда ваша функция используется без аргумента. Вы либо заплатили бы дорогостоящую цену за каждый вызов, либо должны вручную кэшировать значение извне, загрязняя пространство имен и добавляя многословие.

2. Принудительные связанные параметры

Полезный трюк заключается в привязке параметров лямбда к привязке current переменной при создании лямбда. Например:

funcs = [ lambda i=i: i for i in range(10)]

Возвращает список функций, возвращающих 0,1,2,3 ... соответственно. Если поведение изменено, они вместо этого привяжут i к значению времени вызова для i, поэтому вы получите список функций, которые все вернули 9.

Единственным способом реализации этого в противном случае было бы создать дальнейшее закрытие с привязкой i, то есть:

def make_func(i): return lambda: i
funcs = [make_func(i) for i in range(10)]

3. Introspection

Рассмотрим код:

def foo(a='test', b=100, c=[]):
   print a,b,c

Мы можем получить информацию о аргументах и ​​значениях по умолчанию с помощью модуля inspect, который

>>> inspect.getargspec(foo)
(['a', 'b', 'c'], None, None, ('test', 100, []))

информация очень полезна для таких вещей, как создание документов, метапрограммирование, декораторы и т. д.

Теперь предположим, что поведение по умолчанию может быть изменено так, что это эквивалентно:

_undefined = object()  # sentinel value

def foo(a=_undefined, b=_undefined, c=_undefined)
    if a is _undefined: a='test'
    if b is _undefined: b=100
    if c is _undefined: c=[]

Однако мы потеряли способность интроспекции и посмотрим, какие аргументы по умолчанию равны . Поскольку объекты не были построены, мы никогда не сможем их захватить, не называя функцию. Самое лучшее, что мы могли бы сделать, это сохранить исходный код и вернуть его как строку.

14
задан Kyaw Thurein 21 August 2011 в 12:24
поделиться

5 ответов

Когда вы планируете задание, вы можете установить JobDataMap на объект JobDetail и передать его вашему планировщику, есть некоторые ограничения, описанные в учебнике quartz.net . Задание может получить доступ к данным через:

JobDataMap dataMap = context.JobDetail.JobDataMap;

Однако я предпочитаю получать доступ к моей конфигурации заданий через репозиторий, введенный в задание.

4
ответ дан Andreas 20 August 2018 в 17:45
поделиться
  • 1
    Спасибо за ваш ответ, но я ищу, как передать объекты из внешнего приложения. – Kyaw Thurein 2 September 2011 в 02:08
  • 2
    Это то, что мне также нужно знать ... все еще ищут – evermean 3 December 2012 в 00:16
  • 3
    Как вы вводите свой репозиторий без использования JobDataMap? Или это только репо, которое вы вводите? – David Clarke 18 February 2015 в 02:20

У меня были неожиданные результаты с ответом Hillstuk выше в многопоточных средах. Вот мое решение, использующее Newtonsoft ... Наслаждайтесь

public void InitJob() {

    MyClass data = new MyClass {Foo = “Foo fighters”}; 

    /* a unique identifier for demonstration purposes.. Use your own concoction here. */
    int uniqueIdentifier = new Random().Next(int.MinValue, int.MaxValue); 

    IJobDetail newJob = JobBuilder.Create<MyAwesomeJob>()
    .UsingJobData("JobData", JsonConvert.SerializeObject(data))
    .WithIdentity($"job-{uniqueIdentifier}", "main")                
    .Build();

}

/* the execute method */
public class MyAwesomeJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {                   
        var jobData = JsonConvert.DeserializeObject<MyClass>(context.JobDetail.JobDataMap.GetString("JobData"));    
    }
}

/* for completeness */
public class MyClass {
    string Foo { get; set; } 
}
2
ответ дан Greg R Taylor 20 August 2018 в 17:45
поделиться

Есть два способа передать объект, который можно получить при выполнении задания Quartz:

Передайте экземпляр в карте данных. Когда вы установите задание вверх, добавьте свой экземпляр на карту с таким ключом:

// Create job etc...
var MyClass _myInstance;
statusJob.JobDataMap.Put("myKey", _myInstance);
// Schedule job...

Извлеките экземпляр в методе Execute() задания следующим образом:

public void Execute(IJobExecutionContext context)
        {
            var dataMap = context.MergedJobDataMap;
            var myInstance = (MyClass)dataMap["myKey"];

ИЛИ

Добавьте экземпляр в контекст планировщика, когда вы установите задание вверх, например:

  ISchedulerFactory schedFact = new StdSchedulerFactory();
  _sched = schedFact.GetScheduler();
  _sched.Start();
  // Create job etc...
  var MyClass _myInstance;
  _sched.Context.Put("myKey", myInstance);
  // Schedule job...

Извлеките экземпляр в методе Execute() для задания следующим образом:

public void Execute(IJobExecutionContext context)
        {
            var schedulerContext = context.Scheduler.Context;
            var myInstance = (MyClass)schedulerContext.Get("myKey");
26
ответ дан hillstuk 20 August 2018 в 17:45
поделиться
  • 1
    При использовании JobDataMap, как выполняется сериализация экземпляра MyClass? Нужно ли это связывать с [Serializable]? – Dejan 24 March 2015 в 16:11
  • 2

Вы можете поместить ваш экземпляр / объект в файл IJobDetail.

 JobDataMap m = new JobDataMap();
  m.Put("Class1", new Class1(){name="xxx"});


  IJobDetail job = JobBuilder.Create<Job>()
            .WithIdentity("myJob", "group1")
            .UsingJobData(m)//class object
            .UsingJobData("name2", "Hello World!")
            .Build();

использование

  public void Execute(IJobExecutionContext context)
        {
 JobDataMap dataMap = context.JobDetail.JobDataMap;
            Class1 class1 = (Class1)dataMap.Get("Class1");
string x = class1.name;
}
1
ответ дан Lakmal 20 August 2018 в 17:45
поделиться

Я передал объект следующим образом

JobDetail job1 = JobBuilder.newJob(JobAutomation.class)
                .usingJobData("path", path)
                .withIdentity("job2", "group2").build();

        CronTrigger trigger1 = TriggerBuilder.newTrigger()
                .withIdentity("cronTrigger2", "group2")
                .withSchedule(CronScheduleBuilder.cronSchedule("40 27 11 * * ?"))
                .build();

получить jobdatamap следующими строками кода

JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String path =dataMap.getString("path");
0
ответ дан Shashi3456643 20 August 2018 в 17:45
поделиться
  • 1
    JobDataMap dataMap = context.getMergedJobDataMap (); предпочтительнее – Roger Willcocks 21 July 2018 в 22:39
Другие вопросы по тегам:

Похожие вопросы: