选择活动

Pick 活动简化了对一组事件触发器(后跟其相应的处理程序)的建模。 Pick 活动包含 PickBranch 活动的集合,其中每个 PickBranch 都是一个 Trigger 活动与一个 Action 活动之间的配对。 执行时,并行执行所有分支的触发器。 一个触发器完成后,将执行其相应的动作,并且取消所有其他触发器。 .NET Framework 4.6.1Pick 活动的行为类似于 .NET Framework 3.5 ListenActivity 活动。

以下屏幕截图来自使用 Pick 活动 SDK 示例,显示了一个包含两个分支的 Pick 活动。 一个分支有一个名为 “读取输入”的触发器,该触发器是从命令行读取输入的自定义活动。 另一个分支具有一个 Delay 活动触发器。 如果 读取输入 活动在活动完成之前 Delay 接收数据, Delay 则会取消延迟,并将问候语写入控制台。 否则,如果 读取输入 活动未在分配的时间接收数据,则会取消该活动,并将超时消息写入控制台。 这是用于向任何动作添加超时的常见的模式。

Pick 活动

最佳做法

使用 Pick 时,执行的分支是首先完成其触发器的分支。 从概念上讲,所有触发器都并行执行,并且一个触发器会在由于另一个触发器完成而被取消之前执行它的大部分逻辑。 考虑到这一点,使用 Pick 活动时要遵循的一般准则是将触发器视为表示单个事件,并将尽可能少的逻辑放入其中。 理想情况下,触发器应包含足够的逻辑以接收事件,并且该事件的所有处理都应在分支的动作中完成。 此方法可最大程度地减少触发器执行之间的重叠量。 例如,假设有两个 Pick 触发器,其中每个触发器包含一个 Receive 活动,然后再是其他逻辑。 如果其他逻辑引入空闲点,则两 Receive 个活动都有可能成功完成。 一个触发器将完全完成,而另一个触发器将部分完成。 在某些情况下,接受消息,然后部分完成消息处理是不可接受的。 因此,使用 WF 内置的消息传递活动(如 ReceiveSendReply)时,尽管通常在触发器中使用 Receive,但如有可能应将 SendReply 和其他逻辑放入操作中。

在设计器中使用 Pick 活动

若要在设计器中使用 Pick,请查找工具箱中的 PickPickBranch 。 将 Pick 拖放到画布上。 默认情况下,设计器中的新 选取 活动将包含两个分支。 若要添加其他分支,请拖动 PickBranch 活动并将其拖放到现有分支旁边。 可将活动拖放到 Pick 活动上任何 PickBranch 的“触发器”区域或“操作”区域中。

在代码中使用选择活动

使用 Pick 活动的方法是用 Branches 活动填充它的 PickBranch 集合。 每个 PickBranch 活动都有一个 Trigger 类型 Activity的属性。 当指定活动完成执行后,Action 将立即执行。

下面的代码示例演示如何使用 Pick 活动为从控制台读取行的活动实现超时。

Sequence body = new Sequence()
{
    Variables = { name },
    Activities =
   {
       new System.Activities.Statements.Pick
        {
           Branches =
           {
               new PickBranch
               {
                   Trigger = new ReadLine
                   {
                      Result = name,
                      BookmarkName = "name"
                   },
                   Action = new WriteLine
                   {
                       Text = ExpressionServices.Convert<string>(ctx => "Hello " +
                           name.Get(ctx))
                   }
               },
               new PickBranch
               {
                   Trigger = new Delay
                   {
                      Duration = new TimeSpan(0, 0, 5)
                   },
                   Action = new WriteLine
                   {
                      Text = "Time is up."
                   }
               }
           }
       }
   }
};
<Sequence xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Sequence.Variables>
    <Variable x:TypeArguments="x:String" Name="username" />
  </Sequence.Variables>
  <Pick>
    <PickBranch>
      <PickBranch.Trigger>
        <ReadLine BookmarkName="name" Result="username" />
      </PickBranch.Trigger>
      <WriteLine>[String.Concat("Hello ", username)]</WriteLine>
    </PickBranch>
    <PickBranch>
      <PickBranch.Trigger>
        <Delay>00:00:05</Delay>
      </PickBranch.Trigger>
      <WriteLine>Time is up.</WriteLine>
    </PickBranch>
  </Pick>
</Sequence>