- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
很多的软件项目中都会使用到定时任务、定时轮询数据库同步,定时邮件通知等功能。.NET Framework具有“内置”定时器功能,通过System.Timers.Timer类。在使用Timer类需要面对的问题:计时器没有持久化机制;计时器具有不灵活的计划(仅能设置开始时间和重复间隔,没有基于日期,时间等);计时器不使用线程池(每个定时器一个线程);计时器没有真正的管理方案 - 你必须编写自己的机制,以便能够记住,组织和检索任务的名称等.
如果需要在.NET实现定时器的功能,可以尝试使用以下这款开源免费的组件Quartz.Net组件。目前Quartz.NET版本为3.0,修改了原来的一些问题:修复由于线程本地存储而不能与AdoJobStore协同工作的调度器信令;线程局部状态完全删除;quartz.serializer.type是必需的,即使非序列化RAMJobStore正在使用;JSON序列化错误地称为序列化回调.
一.Quart.NET概述: 。
Quartz是一个作业调度系统,可以与任何其他软件系统集成或一起使用。作业调度程序是一个系统,负责在执行预处理程序时执行(或通知)其他软件组件 - 确定(调度)时间到达。Quartz是非常灵活的,并且包含多个使用范例,可以单独使用或一起使用,以实现您所需的行为,并使您能够以您的项目看起来最“自然”的方式编写代码。组件的使用非常轻便,并且需要非常少的设置/配置 - 如果您的需求相对基础,它实际上可以使用“开箱即用”。Quartz是容错的,并且可以在系统重新启动之间保留(记住)您的预定作业。尽管Quartz对于在给定的时间表上简单地运行某些系统进程非常有用,但当您学习如何使用Quartz来驱动应用程序的业务流程时,Quartz的全部潜能可以实现.
Quartz是作为一个小的动态链接库(.dll文件)分发的,它包含所有的核心Quartz功能。 此功能的主要接口(API)是调度程序接口。 它提供简单的操作,如调度/非调度作业,启动/停止/暂停调度程序。如果你想安排你自己的软件组件执行,他们必须实现简单的Job接口,它包含方法execute()。 如果希望在计划的触发时间到达时通知组件,则组件应实现TriggerListener或JobListener接口。主要的Quartz'进程'可以在您自己的应用程序或独立应用程序(使用远程接口)中启动和运行.
二.Quartz.NET主体类和方法解析:
1.StdSchedulerFactory类:创建QuartzScheduler实例.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/// <summary>
/// 返回此工厂生成的调度程序的句柄。
/// </summary>
/// <remarks>
///如果<see cref =“Initialize()”/>方法之一没有先前调用,然后是默认(no-arg)<see cref =“Initialize()”/>方法将被这个方法调用。
/// </remarks>
public
virtual
IScheduler GetScheduler()
{
if
(cfg ==
null
)
{
Initialize();
}
SchedulerRepository schedRep = SchedulerRepository.Instance;
IScheduler sched = schedRep.Lookup(SchedulerName);
if
(sched !=
null
)
{
if
(sched.IsShutdown)
{
schedRep.Remove(SchedulerName);
}
else
{
return
sched;
}
}
sched = Instantiate();
return
sched;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
interface
ISchedulerFactory
{
/// <summary>
/// Returns handles to all known Schedulers (made by any SchedulerFactory
/// within this app domain.).
/// </summary>
ICollection<IScheduler> AllSchedulers {
get
; }
/// <summary>
/// Returns a client-usable handle to a <see cref="IScheduler" />.
/// </summary>
IScheduler GetScheduler();
/// <summary>
/// Returns a handle to the Scheduler with the given name, if it exists.
/// </summary>
IScheduler GetScheduler(
string
schedName);
}
|
2.JobDetailImpl:传递给定作业实例的详细信息属性.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/// <summary>
/// 获取或设置与<see cref =“IJob”/>相关联的<see cref =“JobDataMap”/>。
/// </summary>
public
virtual
JobDataMap JobDataMap
{
get
{
if
(jobDataMap ==
null
)
{
jobDataMap =
new
JobDataMap();
}
return
jobDataMap;
}
set
{ jobDataMap = value; }
}
|
3.JobKey:键由名称和组组成,名称必须是唯一的,在组内。 如果只指定一个组,则默认组将使用名称.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[Serializable]
public
sealed
class
JobKey : Key<JobKey>
{
public
JobKey(
string
name) :
base
(name,
null
)
{
}
public
JobKey(
string
name,
string
group) :
base
(name, group)
{
}
public
static
JobKey Create(
string
name)
{
return
new
JobKey(name,
null
);
}
public
static
JobKey Create(
string
name,
string
group)
{
return
new
JobKey(name, group);
}
}
|
4.StdSchedulerFactory.Initialize()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
/// <summary>
/// 使用初始化<see cref =“ISchedulerFactory”/>
///给定键值集合对象的内容。
/// </summary>
public
virtual
void
Initialize(NameValueCollection props)
{
cfg =
new
PropertiesParser(props);
ValidateConfiguration();
}
protected
virtual
void
ValidateConfiguration()
{
if
(!cfg.GetBooleanProperty(PropertyCheckConfiguration,
true
))
{
// should not validate
return
;
}
// determine currently supported configuration keys via reflection
List<
string
> supportedKeys =
new
List<
string
>();
List<FieldInfo> fields =
new
List<FieldInfo>(GetType().GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy));
// choose constant string fields
fields = fields.FindAll(field => field.FieldType ==
typeof
(
string
));
// read value from each field
foreach
(FieldInfo field
in
fields)
{
string
value = (
string
) field.GetValue(
null
);
if
(value !=
null
&& value.StartsWith(ConfigurationKeyPrefix) && value != ConfigurationKeyPrefix)
{
supportedKeys.Add(value);
}
}
// now check against allowed
foreach
(
string
configurationKey
in
cfg.UnderlyingProperties.AllKeys)
{
if
(!configurationKey.StartsWith(ConfigurationKeyPrefix) || configurationKey.StartsWith(ConfigurationKeyPrefixServer))
{
// don't bother if truly unknown property
continue
;
}
bool
isMatch =
false
;
foreach
(
string
supportedKey
in
supportedKeys)
{
if
(configurationKey.StartsWith(supportedKey, StringComparison.InvariantCulture))
{
isMatch =
true
;
break
;
}
}
if
(!isMatch)
{
throw
new
SchedulerConfigException(
"Unknown configuration property '"
+ configurationKey +
"'"
);
}
}
}
|
三.Quartz.NET的基本应用:
下面提供一些较为通用的任务处理代码:
1.任务处理帮助类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
/// <summary>
/// 任务处理帮助类
/// </summary>
public
class
QuartzHelper
{
public
QuartzHelper() { }
public
QuartzHelper(
string
quartzServer,
string
quartzPort)
{
Server = quartzServer;
Port = quartzPort;
}
/// <summary>
/// 锁对象
/// </summary>
private
static
readonly
object
Obj =
new
object
();
/// <summary>
/// 方案
/// </summary>
private
const
string
Scheme =
"tcp"
;
/// <summary>
/// 服务器的地址
/// </summary>
public
static
string
Server {
get
;
set
; }
/// <summary>
/// 服务器的端口
/// </summary>
public
static
string
Port {
get
;
set
; }
/// <summary>
/// 缓存任务所在程序集信息
/// </summary>
private
static
readonly
Dictionary<
string
, Assembly> AssemblyDict =
new
Dictionary<
string
, Assembly>();
/// <summary>
/// 程序调度
/// </summary>
private
static
IScheduler _scheduler;
/// <summary>
/// 初始化任务调度对象
/// </summary>
public
static
void
InitScheduler()
{
try
{
lock
(Obj)
{
if
(_scheduler !=
null
)
return
;
//配置文件的方式,配置quartz实例
ISchedulerFactory schedulerFactory =
new
StdSchedulerFactory();
_scheduler = schedulerFactory.GetScheduler();
}
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
/// <summary>
/// 启用任务调度
/// 启动调度时会把任务表中状态为“执行中”的任务加入到任务调度队列中
/// </summary>
public
static
void
StartScheduler()
{
try
{
if
(_scheduler.IsStarted)
return
;
//添加全局监听
_scheduler.ListenerManager.AddTriggerListener(
new
CustomTriggerListener(), GroupMatcher<TriggerKey>.AnyGroup());
_scheduler.Start();
//获取所有执行中的任务
List<TaskModel> listTask = TaskHelper.GetAllTaskList().ToList();
if
(listTask.Count > 0)
{
foreach
(TaskModel taskUtil
in
listTask)
{
try
{
ScheduleJob(taskUtil);
}
catch
(Exception e)
{
throw
new
Exception(taskUtil.TaskName,e);
}
}
}
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
/// <summary>
/// 启用任务
/// <param name="task">任务信息</param>
/// <param name="isDeleteOldTask">是否删除原有任务</param>
/// <returns>返回任务trigger</returns>
/// </summary>
public
static
void
ScheduleJob(TaskModel task,
bool
isDeleteOldTask =
false
)
{
if
(isDeleteOldTask)
{
//先删除现有已存在任务
DeleteJob(task.TaskID.ToString());
}
//验证是否正确的Cron表达式
if
(ValidExpression(task.CronExpressionString))
{
IJobDetail job =
new
JobDetailImpl(task.TaskID.ToString(), GetClassInfo(task.AssemblyName, task.ClassName));
//添加任务执行参数
job.JobDataMap.Add(
"TaskParam"
, task.TaskParam);
CronTriggerImpl trigger =
new
CronTriggerImpl
{
CronExpressionString = task.CronExpressionString,
Name = task.TaskID.ToString(),
Description = task.TaskName
};
_scheduler.ScheduleJob(job, trigger);
if
(task.Status == TaskStatus.STOP)
{
JobKey jk =
new
JobKey(task.TaskID.ToString());
_scheduler.PauseJob(jk);
}
else
{
List<DateTime> list = GetNextFireTime(task.CronExpressionString, 5);
foreach
(var time
in
list)
{
LogHelper.WriteLog(time.ToString(CultureInfo.InvariantCulture));
}
}
}
else
{
throw
new
Exception(task.CronExpressionString +
"不是正确的Cron表达式,无法启动该任务!"
);
}
}
/// <summary>
/// 初始化 远程Quartz服务器中的,各个Scheduler实例。
/// 提供给远程管理端的后台,用户获取Scheduler实例的信息。
/// </summary>
public
static
void
InitRemoteScheduler()
{
try
{
NameValueCollection properties =
new
NameValueCollection
{
[
"quartz.scheduler.instanceName"
] =
"ExampleQuartzScheduler"
,
[
"quartz.scheduler.proxy"
] =
"true"
,
[
"quartz.scheduler.proxy.address"
] =
string
.Format(
"{0}://{1}:{2}/QuartzScheduler"
, Scheme, Server, Port)
};
ISchedulerFactory sf =
new
StdSchedulerFactory(properties);
_scheduler = sf.GetScheduler();
}
catch
(Exception ex)
{
throw
new
Exception(ex.StackTrace);
}
}
/// <summary>
/// 删除现有任务
/// </summary>
/// <param name="jobKey"></param>
public
static
void
DeleteJob(
string
jobKey)
{
try
{
JobKey jk =
new
JobKey(jobKey);
if
(_scheduler.CheckExists(jk))
{
//任务已经存在则删除
_scheduler.DeleteJob(jk);
}
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
/// <summary>
/// 暂停任务
/// </summary>
/// <param name="jobKey"></param>
public
static
void
PauseJob(
string
jobKey)
{
try
{
JobKey jk =
new
JobKey(jobKey);
if
(_scheduler.CheckExists(jk))
{
//任务已经存在则暂停任务
_scheduler.PauseJob(jk);
}
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
/// <summary>
/// 恢复运行暂停的任务
/// </summary>
/// <param name="jobKey">任务key</param>
public
static
void
ResumeJob(
string
jobKey)
{
try
{
JobKey jk =
new
JobKey(jobKey);
if
(_scheduler.CheckExists(jk))
{
//任务已经存在则暂停任务
_scheduler.ResumeJob(jk);
}
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
/// <summary>
/// 获取类的属性、方法
/// </summary>
/// <param name="assemblyName">程序集</param>
/// <param name="className">类名</param>
private
static
Type GetClassInfo(
string
assemblyName,
string
className)
{
try
{
assemblyName = FileHelper.GetAbsolutePath(assemblyName +
".dll"
);
Assembly assembly =
null
;
if
(!AssemblyDict.TryGetValue(assemblyName,
out
assembly))
{
assembly = Assembly.LoadFrom(assemblyName);
AssemblyDict[assemblyName] = assembly;
}
Type type = assembly.GetType(className,
true
,
true
);
return
type;
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
/// <summary>
/// 停止任务调度
/// </summary>
public
static
void
StopSchedule()
{
try
{
//判断调度是否已经关闭
if
(!_scheduler.IsShutdown)
{
//等待任务运行完成
_scheduler.Shutdown(
true
);
}
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
/// <summary>
/// 校验字符串是否为正确的Cron表达式
/// </summary>
/// <param name="cronExpression">带校验表达式</param>
/// <returns></returns>
public
static
bool
ValidExpression(
string
cronExpression)
{
return
CronExpression.IsValidExpression(cronExpression);
}
/// <summary>
/// 获取任务在未来周期内哪些时间会运行
/// </summary>
/// <param name="CronExpressionString">Cron表达式</param>
/// <param name="numTimes">运行次数</param>
/// <returns>运行时间段</returns>
public
static
List<DateTime> GetNextFireTime(
string
CronExpressionString,
int
numTimes)
{
if
(numTimes < 0)
{
throw
new
Exception(
"参数numTimes值大于等于0"
);
}
//时间表达式
ITrigger trigger = TriggerBuilder.Create().WithCronSchedule(CronExpressionString).Build();
IList<DateTimeOffset> dates = TriggerUtils.ComputeFireTimes(trigger
as
IOperableTrigger,
null
, numTimes);
List<DateTime> list =
new
List<DateTime>();
foreach
(DateTimeOffset dtf
in
dates)
{
list.Add(TimeZoneInfo.ConvertTimeFromUtc(dtf.DateTime, TimeZoneInfo.Local));
}
return
list;
}
public
static
object
CurrentTaskList()
{
throw
new
NotImplementedException();
}
/// <summary>
/// 获取当前执行的Task 对象
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public
static
TaskModel GetTaskDetail(IJobExecutionContext context)
{
TaskModel task =
new
TaskModel();
if
(context !=
null
)
{
task.TaskID = Guid.Parse(context.Trigger.Key.Name);
task.TaskName = context.Trigger.Description;
task.RecentRunTime = DateTime.Now;
task.TaskParam = context.JobDetail.JobDataMap.Get(
"TaskParam"
) !=
null
? context.JobDetail.JobDataMap.Get(
"TaskParam"
).ToString() :
""
;
}
return
task;
}
}
|
2.设置执行中的任务:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
public
class
TaskBll
{
private
readonly
TaskDAL _dal =
new
TaskDAL();
/// <summary>
/// 获取任务列表
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public
PageOf<TaskModel> GetTaskList(
int
pageIndex,
int
pageSize)
{
return
_dal.GetTaskList(pageIndex, pageSize);
}
/// <summary>
/// 读取数据库中全部的任务
/// </summary>
/// <returns></returns>
public
List<TaskModel> GetAllTaskList()
{
return
_dal.GetAllTaskList();
}
/// <summary>
///
/// </summary>
/// <param name="taskId"></param>
/// <returns></returns>
public
TaskModel GetById(
string
taskId)
{
throw
new
NotImplementedException();
}
/// <summary>
/// 删除任务
/// </summary>
/// <param name="taskId"></param>
/// <returns></returns>
public
bool
DeleteById(
string
taskId)
{
return
_dal.UpdateTaskStatus(taskId, -1);
}
/// <summary>
/// 修改任务
/// </summary>
/// <param name="taskId"></param>
/// <param name="status"></param>
/// <returns></returns>
public
bool
UpdateTaskStatus(
string
taskId,
int
status)
{
return
_dal.UpdateTaskStatus(taskId, status);
}
/// <summary>
/// 修改任务的下次启动时间
/// </summary>
/// <param name="taskId"></param>
/// <param name="nextFireTime"></param>
/// <returns></returns>
public
bool
UpdateNextFireTime(
string
taskId, DateTime nextFireTime)
{
return
_dal.UpdateNextFireTime(taskId, nextFireTime);
}
/// <summary>
/// 根据任务Id 修改 上次运行时间
/// </summary>
/// <param name="taskId"></param>
/// <param name="recentRunTime"></param>
/// <returns></returns>
public
bool
UpdateRecentRunTime(
string
taskId, DateTime recentRunTime)
{
return
_dal.UpdateRecentRunTime(taskId, recentRunTime);
}
/// <summary>
/// 根据任务Id 获取任务
/// </summary>
/// <param name="taskId"></param>
/// <returns></returns>
public
TaskModel GetTaskById(
string
taskId)
{
return
_dal.GetTaskById(taskId);
}
/// <summary>
/// 添加任务
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public
bool
Add(TaskModel task)
{
return
_dal.Add(task);
}
/// <summary>
/// 修改任务
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public
bool
Edit(TaskModel task)
{
return
_dal.Edit(task);
}
}
|
3.任务实体:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
/// <summary>
/// 任务实体
/// </summary>
public
class
TaskModel
{
/// <summary>
/// 任务ID
/// </summary>
public
Guid TaskID {
get
;
set
; }
/// <summary>
/// 任务名称
/// </summary>
public
string
TaskName {
get
;
set
; }
/// <summary>
/// 任务执行参数
/// </summary>
public
string
TaskParam {
get
;
set
; }
/// <summary>
/// 运行频率设置
/// </summary>
public
string
CronExpressionString {
get
;
set
; }
/// <summary>
/// 任务运频率中文说明
/// </summary>
public
string
CronRemark {
get
;
set
; }
/// <summary>
/// 任务所在DLL对应的程序集名称
/// </summary>
public
string
AssemblyName {
get
;
set
; }
/// <summary>
/// 任务所在类
/// </summary>
public
string
ClassName {
get
;
set
; }
public
TaskStatus Status {
get
;
set
; }
/// <summary>
/// 任务创建时间
/// </summary>
public
DateTime? CreatedTime {
get
;
set
; }
/// <summary>
/// 任务修改时间
/// </summary>
public
DateTime? ModifyTime {
get
;
set
; }
/// <summary>
/// 任务最近运行时间
/// </summary>
public
DateTime? RecentRunTime {
get
;
set
; }
/// <summary>
/// 任务下次运行时间
/// </summary>
public
DateTime? NextFireTime {
get
;
set
; }
/// <summary>
/// 任务备注
/// </summary>
public
string
Remark {
get
;
set
; }
/// <summary>
/// 是否删除
/// </summary>
public
int
IsDelete {
get
;
set
; }
}
|
4.配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# You can configure your scheduler in either <
quartz
> configuration section
# or in quartz properties file
# Configuration section has precedence
quartz.scheduler.instanceName = ExampleQuartzScheduler
# configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal
# job initialization plugin handles our xml reading, without it defaults are used
# quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
# quartz.plugin.xml.fileNames = ~/quartz_jobs.xml
# export this server to remoting context
quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
quartz.scheduler.exporter.port = 555
quartz.scheduler.exporter.bindName = QuartzScheduler
quartz.scheduler.exporter.channelType = tcp
quartz.scheduler.exporter.channelName = httpQuartz
|
四.总结:
在项目中比较多的使用到定时任务的功能,今天的介绍的组件可以很好的完成一些定时任务的要求。这篇文章主要是作为引子,简单的介绍了组件的背景和组件的使用方式,如果项目中需要使用,可以进行更加深入的了解.
原文链接:http://www.cnblogs.com/pengze0902/p/6128558.html 。
最后此篇关于详解免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)的文章就讲到这里了,如果你想了解更多关于详解免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
创建使用.NET框架的asp.net页面时,访问该页面的客户端是否需要在其计算机上安装.NET框架? IE。用户访问www.fakesite.com/default.aspx,如果他们没有安装框架,他
我阅读了很多不同的博客和 StackOverflow 问题,试图找到我的问题的答案,但最后我找不到任何东西,所以我想自己问这个问题。 我正在构建一个应用程序,其中有一个长时间运行的工作线程,它执行一些
已锁定。这个问题及其答案是locked因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。 我一直想知道为什么微软为这样一个伟大的平台选择了一个如此奇怪的、对搜索引擎不友好的名称。他们就
.Net Framework .Net .NET Standard的区别 1、.NET Framework 在未来.NET Framework或许成为过去时,目前还是有很多地方在使用的。这一套
如果有选择的话,您会走哪条路? ASP.NET Webforms + ASP.NET AJAX 或 ASP.NET MVC + JavaScript Framework of your Choice
我有一个 Web 服务,它通过专用连接通过 https 使用第三方 Web 服务,我应用了 ServicePointManager.ServerCertificateValidationCallbac
为什么我应该选择ASP.NET Web Application (.NET Framework)而不是ASP.NET Core Web Application (.NET Framework)? 我在
我在网络上没有找到任何关于包含 .NET Standard、.NET Core 和 .NET Framework 项目的 .NET 解决方案的公认命名约定。 就我而言,我们在 .NET 框架项目中有以
.NET Compact 是 .NET 的完美子集吗? 假设我考虑了屏幕大小和其他限制并避免了 .NET Compact 不支持的类和方法,或者 .NET Compact 是一个不同且不兼容的 GUI
我已经阅读了所有我能找到的关于 connectionManagement 中的 maxconnection 设置的文章:即 http://support.microsoft.com/kb/821268
我现在正在使用asp.net mvc,想知道使用内置的Json或 Json.Net哪个是更好的选择,但我不确定一个人是否比另一个人有优势。 另外,如果我确实选择沿用Json.Net的路线,那么我应该选
在 Visual Studio 中,您至少可以创建三种不同类型的类库: 类库(.NET Framework) 类库(.NET 标准) 类库(.NET Core) 虽然第一个是我们多年来一直使用的,但我
.NET 和 ASP.NET 之间有什么区别?它们有什么关系? 最佳答案 ASP.Net 基于 .Net 框架构建,提供有关 Web 开发的附加功能。 你可以去看看wikipedia article
在安装更高版本(3.0)之前,我需要安装.net框架1.1和2.0吗?或者单独安装 3.0 框架就足够了,并为在早期框架版本上编写的软件提供支持?谢谢 ,丽然 最佳答案 不,您不必安装以前的框架。 我
我正在开发一个项目,人们可以“更新”类别,例如更改类别的名称。我收到以下消息 This is called after clicking update 按钮 with the SQL statemen
.NET 类 System.Net.CookieContainer 线程安全吗? --更新:交 key 答复-- 是否有任何方法可以确保异步请求期间修改的变量(即 HttpWebRequest.Coo
我正在使用 JScript.NET 在我编写的 C# WinForms 应用程序中编写脚本。它工作得很好,但我只是尝试在脚本中放置一些异常处理,但我无法弄清楚如何判断我的 C# 代码抛出了哪种类型的异
我需要你的帮助, 比如我有一个小数类型的变量,我想这样取整。 例如 3.0 = 3 3.1 = 4 3.2 = 4 3.3 = 4 3.4 = 4 3.5 = 4 3.6 = 4 3.7 = 4 3.
我使用过这样的代码:http://msdn.microsoft.com/en-us/library/dw70f090.aspx在 ASP.NET 中工作之前访问数据库(2-3 年前)。我没有意识到我正
自 ConfigurationManager .NET Standard 中不存在,检索正在执行的程序集的应用程序设置的最佳方法是什么,无论是 web.config或 appSettings.{env
我是一名优秀的程序员,十分优秀!