【问题标题】:WF 4 OnUnhandledException not hitWF 4 OnUnhandledException 未命中
【发布时间】:2015-05-18 11:32:06
【问题描述】:

我创建了一个自定义活动,其中包含另一个活动作为主体。

    [Browsable(false)]
    public Activity Body { get; set; }

    protected override void Execute(NativeActivityContext context)
    {
        ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete), OnFaulted);
    }

    private void OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
    {
        throw new Exception(propagatedException.Message);
    }

当在 Body 执行过程中抛出异常时,会命中 OnFaulted 的 ma handler。

我的执行从调用 WorkflowApplication 类的静态方法 Run 开始。我的 WorkflowApplication 实例有一个与 OnUnhandledException 事件关联的处理程序。

 instance.OnUnhandledException +=
                       delegate(WorkflowApplicationUnhandledExceptionEventArgs args)
                    {
                        Console.WriteLine(args.ExceptionSource);
                        waitEvent.Set();
                        return UnhandledExceptionAction.Cancel;
                    };

但是无论在 Body 中托管的 Activity 执行时会发生什么,我都无法到达上面定义的处理程序。我认为如果我从 OnFaulted 抛出异常,我将能够将流重定向到 OnUnhandledException,但我错了。有什么想法吗?

我需要这个来集中我的错误,检查它们并相应地显示消息。另外我需要一种方法来停止执行等等,我不想在整个应用程序中定义处理程序。有没有办法做到这一点?

【问题讨论】:

  • 听起来像是在调用 ScheduleActivity 时定义了异常处理程序会抑制任何进一步的异常。看一眼代码库可能会告诉你这一点(去检查referencesource.microsoft.com 或获取 JustDecompile)。如果您不需要故障处理程序,请传入 null 或调用不接受它的重载。否则,您可能必须添加一个工作流扩展,以允许您的故障处理程序在工作流之外传达此异常,以便您处理它。
  • @Will 我是否在我的 OnFaulted 中添加了 faultContext.HandleFault() 并解决了坏事,继续执行并到达 Completed 事件处理程序。你激励我使用扩展,我阅读了一些文章,我将开始研究它。非常感谢!
  • 好。您可以在下面的答案中添加一些关于您实际解决问题的详细信息以结束此问题。

标签: workflow-foundation-4 workflow-foundation workflow-activity


【解决方案1】:

正如威尔所建议的,我将发布我为处理我的场景所做的事情。

基本上,在我的自定义活动中,我主持了一个分配:

    [Browsable(false)]
    public Activity Body { get; set; }

    Activity System.Activities.Presentation.IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
    {
        return new Assignment()
        {
            Body = new Assign() { DisplayName = "" }
        };
    }

我已将此代码添加到我的 Execute 方法中:

ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete), OnFaulted);

我试图通过给一个数组一个负值作为索引来运行这个赋值,并且抛出了一个异常。这以某种方式结束了我的执行,但没有命中我的 WorkflowApplication 实例事件的处理程序。

这是执行主体时作为回调给出的方法(在我们的例子中是分配活动):

    private void OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
    {
        faultContext.HandleFault();
        CommunicationExtension ce = faultContext.GetExtension<CommunicationExtension>();

        ITextExpression toTextExpression = (propagatedFrom.Activity as Assign).To.Expression as ITextExpression;

        string valueTextExpression = string.Empty;
        if ((propagatedFrom.Activity as Assign).Value != null)
        {
            if ((propagatedFrom.Activity as Assign).Value.Expression != null)
                valueTextExpression = (propagatedFrom.Activity as Assign).Value.Expression.ToString();
        }


        if (ce != null)
        {
            ce.AddData(string.Format("{0} found on Assignment definition [{1} = {2}]", propagatedException.Message, toTextExpression.ExpressionText, valueTextExpression));
        }
    }

诀窍是调用:

 faultContext.HandleFault();

并使用 CommunicationExtension 允许我在 GUI 中显示错误。

这个类的代码很简单:

public class CommunicationExtension
{

    public List<string> Messages { get; set; }

    public CommunicationExtension()
    {
        Messages = new List<string>();
    }

    public void AddData(string message)
    {
        if (string.IsNullOrEmpty(message))
            return;
        Messages.Add(message);
    }
}

使用它来添加扩展:

CommunicationExtension ce = new CommunicationExtension();
instance.Extensions.Add(ce);

instance 是我的 WorkflowApplication 实例。

我了解到,对于工作流应用程序的每个实例,我们都有其扩展类的一个实例。所以我可以从我的所有自定义活动中发送这样的消息,以显示它们的状态。

我希望这个场景也可以帮助其他人。

【讨论】:

    猜你喜欢
    • 2017-11-05
    • 2023-03-25
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多