1.Wait活动首先等待一段指定的时间的流逝,然后在完成.代码如下:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
namespace Goyier.Activities
{
public class Wait : Activity
{
private Guid timerId;
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(Wait));
//等待时间间隔
public TimeSpan Duration
{
get
{
return(TimeSpan) base.GetValue(DurationProperty);
}
set
{
base.SetValue(DurationProperty, value);
}
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
WorkflowQueuingService qservice = executionContext.GetService<WorkflowQueuingService>();
timerId = Guid.NewGuid();
WorkflowQueue queue = qservice.CreateWorkflowQueue(timerId, true);
queue.QueueItemAvailable+=new EventHandler<QueueEventArgs>(this.ContinueAt);
//自定的计时器服务
TimerService timerService = executionContext.GetService<TimerService>();
timerService.SetTime(timerId,Duration);
Console.WriteLine(Duration);
return ActivityExecutionStatus.Executing;
}
void ContinueAt(object sender,QueueEventArgs e)
{
ActivityExecutionContext context = sender as ActivityExecutionContext;
WorkflowQueuingService qservice = context.GetService<WorkflowQueuingService>();
WorkflowQueue queue = qservice.GetWorkflowQueue(timerId);
qservice.DeleteWorkflowQueue(timerId);
context.CloseActivity();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
namespace Goyier.Activities
{
public class Wait : Activity
{
private Guid timerId;
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(Wait));
//等待时间间隔
public TimeSpan Duration
{
get
{
return(TimeSpan) base.GetValue(DurationProperty);
}
set
{
base.SetValue(DurationProperty, value);
}
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
WorkflowQueuingService qservice = executionContext.GetService<WorkflowQueuingService>();
timerId = Guid.NewGuid();
WorkflowQueue queue = qservice.CreateWorkflowQueue(timerId, true);
queue.QueueItemAvailable+=new EventHandler<QueueEventArgs>(this.ContinueAt);
//自定的计时器服务
TimerService timerService = executionContext.GetService<TimerService>();
timerService.SetTime(timerId,Duration);
Console.WriteLine(Duration);
return ActivityExecutionStatus.Executing;
}
void ContinueAt(object sender,QueueEventArgs e)
{
ActivityExecutionContext context = sender as ActivityExecutionContext;
WorkflowQueuingService qservice = context.GetService<WorkflowQueuingService>();
WorkflowQueue queue = qservice.GetWorkflowQueue(timerId);
qservice.DeleteWorkflowQueue(timerId);
context.CloseActivity();
}
}
}
这个自定义的Wait活动依赖TimerService的实现,TimerServices管理着实际的计时器,在Wait活动的Execute方法中,创建一个WF程序队列并注册了ContinueAt方法,随后调用TimerServices的SetTimer方法,将一个代表计时器的Uid传入方法,当计时器被触发时,TimerServices会把数据压入Wait活动创建的WF程序队列中,当调度器调用ContinueAt方法,并迁移到Closed状态.
2.我们现在定义一个名TimerServices的抽象类,以便为我们的计时器服务提供接口.我们可以实现各种各样的逻辑,代码如下:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
namespace Goyier.Activities
{
public abstract class TimerService
{
public abstract void SetTime(Guid timerId, TimeSpan duration);
public abstract void CancelTime(Guid timeerId);
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
namespace Goyier.Activities
{
public abstract class TimerService
{
public abstract void SetTime(Guid timerId, TimeSpan duration);
public abstract void CancelTime(Guid timeerId);
}
}
3.接下来我们实现一个简单的计时器服务,代码如下:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
using System.Threading;
using Goyier.Activities
namespace Goyier.Services
{
public class SimpleTimerService : TimerService
{
WorkflowRuntime runtime;
Dictionary<Guid, Timer> timers = new Dictionary<Guid, Timer>();
public SimpleTimerService(WorkflowRuntime runtime)
{
this.runtime = runtime;
}
//设置计时器
public override void SetTime(Guid timerId, TimeSpan duration)
{
Guid instanceId = WorkflowEnvironment.WorkflowInstanceId;
Timer timer = new Timer(delegate(object o)
{
WorkflowInstance instance = runtime.GetWorkflow(instanceId);
instance.EnqueueItem(timerId, null, null, null);
}, timerId, duration, new TimeSpan(Timeout.Infinite));
timers.Add(timerId, timer);
}
//取消计时器
public override void CancelTime(Guid timerId)
{
((IDisposable)timers[timerId]).Dispose();
timers.Remove(timerId);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
using System.Threading;
using Goyier.Activities
namespace Goyier.Services
{
public class SimpleTimerService : TimerService
{
WorkflowRuntime runtime;
Dictionary<Guid, Timer> timers = new Dictionary<Guid, Timer>();
public SimpleTimerService(WorkflowRuntime runtime)
{
this.runtime = runtime;
}
//设置计时器
public override void SetTime(Guid timerId, TimeSpan duration)
{
Guid instanceId = WorkflowEnvironment.WorkflowInstanceId;
Timer timer = new Timer(delegate(object o)
{
WorkflowInstance instance = runtime.GetWorkflow(instanceId);
instance.EnqueueItem(timerId, null, null, null);
}, timerId, duration, new TimeSpan(Timeout.Infinite));
timers.Add(timerId, timer);
}
//取消计时器
public override void CancelTime(Guid timerId)
{
((IDisposable)timers[timerId]).Dispose();
timers.Remove(timerId);
}
}
}
4.接下来我们在Wait活动所在的程序集的元数据里加入以下元数据:
Code
[assembly: XmlnsDefinition("http://GuoyiWF/Activities", "Goyier.Activities")]
[assembly: XmlnsDefinition("http://GuoyiWF/Activities", "Goyier.Activities")]
以便将XML名称空间"http://GuoyiWF/Activities"映射到CLR名称空间"Guoyier.Activities".
5.我们新建一个顺序工作控制台应用程序,来进行测试,在项目中新建一个xoml文件,内容如下:
Code
<Wait x:Name="mywait" xmlns="http://GuoyiWF/Activities" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Duration="00:00:10"> </Wait>
<Wait x:Name="mywait" xmlns="http://GuoyiWF/Activities" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Duration="00:00:10"> </Wait>
等待的时间间隔设置为10秒钟
6.执行Wait活动的代码如下: