【问题标题】:workflow foundation multiple tracking participants do not work consistently工作流基础多个跟踪参与者工作不一致
【发布时间】:2015-08-26 09:33:04
【问题描述】:

我在使用 wf4.5 和 C# v4.0.30319 在 win7 下运行的自定义工作流基础跟踪参与者时遇到问题。单个跟踪参与者似乎工作可靠,但是一旦我使用第二个跟踪参与者,无论是否跟踪活动,我都会成为运气游戏。 我已经检查了所有可能的堆栈溢出答案,可能还有所有可用的谷歌结果。

我创建了一个简单的应用程序来演示该行为。

我有一个简单的代码活动:

using System;
using System.Activities;

namespace WorkflowTrackingTestApp
{
    public sealed class CodeActivity1 : CodeActivity
    {
        public InArgument<string> Text { get; set; }

        protected override void Execute( CodeActivityContext context )
        {
            Console.WriteLine( "executing code activity " + typeof( string ).Assembly.ImageRuntimeVersion );
        }
    }
}

它除了打印“正在执行的代码活动和 c# 版本”之外什么都不做。

比我有两个自定义跟踪参与者。请注意,它们都有一个跟踪配置文件,并且配置文件具有不同的名称,因为在另一个线程中建议这可能是问题所在。

namespace ActivityLibrary
{
    using System;
    using System.Activities.Tracking;

    public class EventTrackingParticipant0 : TrackingParticipant
    {
        public EventTrackingParticipant0()
        {
            this.TrackingProfile = new TrackingProfile
            {
                Name = "CustomTrackingProfile0",
                Queries =
                {
                    new WorkflowInstanceQuery
                    {
                        // Limit workflow instance tracking records for started and
                        // completed workflow states.
                        States = {WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed},
                    }
                }
            };
        }

        public Action<TrackingRecord> Received { get; set; }

        protected override void Track( TrackingRecord record, TimeSpan timeout )
        {
            if( Received != null )
            {
                Received.BeginInvoke( record, BeginInvokeCallback, Received );
            }
        }

        private void BeginInvokeCallback( IAsyncResult ar )
        {
            ((Action<TrackingRecord>)ar.AsyncState).EndInvoke( ar );
        }
    }

    public class EventTrackingParticipant1 : TrackingParticipant
    {
        public EventTrackingParticipant1()
        {
            this.TrackingProfile = new TrackingProfile
            {
                Name = "CustomTrackingProfile1",
                Queries =
                {
                    new WorkflowInstanceQuery
                    {
                        // Limit workflow instance tracking records for started and
                        // completed workflow states.
                        States = {WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed},
                    }
                }
            };
        }

        public Action<TrackingRecord> Received { get; set; }

        protected override void Track( TrackingRecord record, TimeSpan timeout )
        {
            if( Received != null )
            {
                Received.BeginInvoke( record, BeginInvokeCallback, Received );
            }
        }

        private void BeginInvokeCallback( IAsyncResult ar )
        {
            ((Action<TrackingRecord>)ar.AsyncState).EndInvoke( ar );
        }

    }
}

对于两个配置文件,代码基本相同。

现在进入主程序:

namespace WorkflowTrackingTestApp
{
    using System;
    using System.Activities;
    using ActivityLibrary;

    class Program
    {
        static void Main( string[] args )
        {
            EventTrackingParticipant0 tp0 = new EventTrackingParticipant0();
            tp0.Received = tr => Console.WriteLine( "tracker0 tracking " + tr.EventTime.ToString( CultureInfo.InvariantCulture ) + " " + tr.RecordNumber);

            EventTrackingParticipant1 tp1 = new EventTrackingParticipant1();
            tp1.Received = tr => Console.WriteLine( "tracker1 tracking " + tr.EventTime.ToString( CultureInfo.InvariantCulture ) + " " + tr.RecordNumber );

            Activity workflow1 = new CodeActivity1();
            WorkflowInvoker wfInvoker = new WorkflowInvoker( workflow1 );

            //add tracking participants
            wfInvoker.Extensions.Add( tp0 );
            wfInvoker.Extensions.Add( tp1 );

            wfInvoker.Invoke( );
        }
    }
}

它添加两个跟踪参与者并执行代码活动。 这是一些可能的结果:

executing code activity v4.0.30319
tracker0 tracking 08/26/2015 09:18:50 0
tracker1 tracking 08/26/2015 09:18:50 0
Press any key to continue . . .

executing code activity v4.0.30319
tracker0 tracking 08/26/2015 09:29:41 0
tracker0 tracking 08/26/2015 09:29:41 4
tracker1 tracking 08/26/2015 09:29:41 0
tracker1 tracking 08/26/2015 09:29:41 4
Press any key to continue . . .

executing code activity v4.0.30319
tracker0 tracking 08/26/2015 09:30:08 0
tracker1 tracking 08/26/2015 09:30:08 0
tracker0 tracking 08/26/2015 09:30:08 4
tracker1 tracking 08/26/2015 09:30:08 4
Press any key to continue . . .

executing code activity v4.0.30319
tracker0 tracking 08/26/2015 09:30:25 0
tracker1 tracking 08/26/2015 09:30:25 0
tracker1 tracking 08/26/2015 09:30:25 4
Press any key to continue . . .

有谁知道这种行为的原因是什么。

【问题讨论】:

    标签: c# c#-4.0 workflow-foundation


    【解决方案1】:

    跟踪参与者是异步执行的,通常与活动执行不在同一个线程中。您的控制台应用程序有时会在参与者之一有时间执行之前退出。例如,如果您添加简单 System.Threading.Thread.Sleep(1000); 在 wfInvoker.Invoke() 之后;您将几乎总是执行所有 4 个处理程序。

    【讨论】:

    • 感谢您的回答。 Thread.Sleep 在我看来像是一种“肮脏”的解决方案。有没有办法让跟踪参与者同步?
    【解决方案2】:

    更改 Track 方法的实现
      if( Received != null )
      {
          Received.BeginInvoke( record, BeginInvokeCallback, Received );
      }
    

      if (Received != null)
          Received(record);
    

    在这种情况下,跟踪参与者将在与活动相同的线程中执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多