none
Rehosted ForEach and ParallelForEach does not work? RRS feed

  • Question

  • I added ForEach<> and ParallelForEach<> activity to my rehosted WF4 application, however the body is not executed at all. I tried building the exact same ForEach activity in Visual Studio, and it works in VS 2010. This blog post does mention about some problem in rehosted ForEach, but it only mention the error when saving and loading a file containing ForEach activity. Any info on why my rehosted ForEach does not work and how to fix it?
    Thursday, November 18, 2010 8:40 AM

Answers

  • Hi Louis, You have linked to the explanation of the problem, and a solution, however I guess I need to clarify it a little. The XAML ist just another symptom the real problem is in the objects you have in the background behind those lovely graphical designers, so you'll see issues no matter what you do with them. Tim
    • Marked as answer by Louis Rhys Wednesday, November 24, 2010 7:32 AM
    Friday, November 19, 2010 3:09 AM
    Moderator

All replies

  • it seems a little strange. it's hard to find the cause from your description.

    can you mail me your repro apps so I can investigate for you?

    sophy_yuye@hotmail.com

    Friday, November 19, 2010 1:16 AM
  • Hi Louis, You have linked to the explanation of the problem, and a solution, however I guess I need to clarify it a little. The XAML ist just another symptom the real problem is in the objects you have in the background behind those lovely graphical designers, so you'll see issues no matter what you do with them. Tim
    • Marked as answer by Louis Rhys Wednesday, November 24, 2010 7:32 AM
    Friday, November 19, 2010 3:09 AM
    Moderator
  • hi tilovell/Tim,

    thank you for your comment and explanation. the linked solution (i noticed it's your blogpost :)) does work for me, ie changing ForEach<> to ForEachWithBodyFactory<> does make it work. however i noticed one simple downside. When I drag ForEachWithBodyFactory to the designer, the program automatically make it ForEach<Int32>, I don't know why, as opposed to asking the user what type the user want to use as the T. Is there a way to make ForEachWithBodyFactory similarly prompt the user?

    I have another question. Does the error exist in these two activity only or with other generic activity? I see there is also Switch<> and probably others.

    Thank you again

    Louis

    Friday, November 19, 2010 6:44 AM
  • You should be able to do it by creating your own Factory class (implement IActivityTemplateFactory) and not give it any DefaultTypeParameterAttribute.

    One general issue behind the weirdness is that WorkflowItemPresenter can be bound to a property that doesn't really exist. In this case the WPF binds it to ModelItem.Handler.Body or something like that, but ModelItem.Handler is null. Another part issue is ModelItem.Handler being null by default, which the factory can solve.

    So in fact the weirdness is nothing to do with the generic type resolution, it just happens to feature on the same activities.
    Tim

    Friday, November 19, 2010 8:00 AM
    Moderator
  • I see your app, but I can't see how you add the toolbox control.

    I created some sample for you, so you can add foreach activity from toolbox and execute the workflow

    xaml.cs

     public partial class MainWindow : Window
        {
            WorkflowDesigner designer;
            public MainWindow()
            {
                InitializeComponent();
                new DesignerMetadata().Register();
                ToolboxItemWrapper wrapper = new ToolboxItemWrapper(typeof(ForEachWithBodyFactory<>));
                ToolboxItemWrapper writeline = new ToolboxItemWrapper(typeof(WriteLine));
                ToolboxItemWrapper delay = new ToolboxItemWrapper(typeof(Delay));
                ToolboxCategory category = new ToolboxCategory("category");
                category.Add(wrapper);
                category.Add(writeline);
                category.Add(delay);
                ToolboxControl control = new ToolboxControl();
                control.Categories.Add(category);

                designer = new WorkflowDesigner();
                Sequence sequence = new Sequence();
                designer.Load(sequence);
                Grid.SetColumn(control, 0);
                Grid.SetColumn(designer.View, 1);
                grid1.Children.Add(control);
                grid1.Children.Add(designer.View);

                Button btn = new Button();
                btn.Click += new RoutedEventHandler(btn_Click);
                Grid.SetColumn(btn, 2);
                grid1.Children.Add(btn);
                Grid.SetColumn(designer.PropertyInspectorView, 3);
                grid1.Children.Add(designer.PropertyInspectorView);
            }

            void btn_Click(object sender, RoutedEventArgs e)
            {
                designer.Flush();
                designer.Save(@"content.xaml");
                Activity activity = ActivityXamlServices.Load(@"content.xaml");
                WorkflowInvoker.Invoke(activity);
            }
        }

     

    xaml

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid Name="grid1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
        </Grid>
    </Window>

    Friday, November 19, 2010 1:03 PM
  • and paste you another xaml.cs version

    with this one, the foreach activity is added to sequence before loaded to designer

    WorkflowDesigner designer;
            public MainWindow()
            {
                InitializeComponent();
                new DesignerMetadata().Register();
                ToolboxItemWrapper wrapper = new ToolboxItemWrapper(typeof(ForEachWithBodyFactory<>));
                ToolboxItemWrapper writeline = new ToolboxItemWrapper(typeof(WriteLine));
                ToolboxItemWrapper delay = new ToolboxItemWrapper(typeof(Delay));
                ToolboxCategory category = new ToolboxCategory("category");
                category.Add(wrapper);
                category.Add(writeline);
                category.Add(delay);
                ToolboxControl control = new ToolboxControl();
                control.Categories.Add(category);

                designer = new WorkflowDesigner();
                Sequence sequence = new Sequence();
                ForEach<string> temp = new ForEach<string>
                {
                    DisplayName = "ForEachFromFactory",
                    Body = new ActivityAction<string>
                    {
                        Argument = new DelegateInArgument<string>("item")
                    }
                };

                sequence.Activities.Add(temp);
                designer.Load(sequence);
                Grid.SetColumn(control, 0);
                Grid.SetColumn(designer.View, 1);
                grid1.Children.Add(control);
                grid1.Children.Add(designer.View);

                Button btn = new Button();
                btn.Click += new RoutedEventHandler(btn_Click);
                Grid.SetColumn(btn, 2);
                grid1.Children.Add(btn);
                Grid.SetColumn(designer.PropertyInspectorView, 3);
                grid1.Children.Add(designer.PropertyInspectorView);
            }

            void btn_Click(object sender, RoutedEventArgs e)
            {
                designer.Flush();
                designer.Save(@"content.xaml");
                Activity activity = ActivityXamlServices.Load(@"content.xaml");
                WorkflowInvoker.Invoke(activity);
            }

    Friday, November 19, 2010 1:18 PM
  • How about TryCatch? is there a factory too?
    Monday, December 6, 2010 11:09 PM
  • TryCatch works a little differently because of underlying object model.

    It actually has a collection (plain collection) of 'Catches' which are neither activities, nor activity actions.
    In contrast to ForEach.Body (the activity action), the collection of catches is always non-null, so a factory isn't needed to actually create it. And catches can be dragged in from toolbox directly, once they are in your toolbox.

    [Also Try's Body and Finally are just regular Activity properties. They don't need to be ActivityAction<T>, because there is no parameter to get passed in.]

    Tim

    Tuesday, December 7, 2010 12:29 AM
    Moderator