Skip to main content

How to: Reduce the Memory Consumption of the Workflow Service

  • 3 minutes to read

The current Workflow Server implementation is not designed for the scenario when workflow definitions are changed very frequently (1 minute), and an updated version should be started in a short time. The refresh operation is executed with the help of the HostManagerActivityProvider class that uses the AssemblyBuilder class to create activities from XAML strings. This approach allows end-users to add runtime activities on the toolbox and to reuse these activities as components in the runtime workflow designer. So, with each refresh operation, a new assembly is created and loaded into the current AppDomain. This operation requires additional unmanaged memory (about 100Kb per each assembly). All the loaded assemblies are unloaded when the entire AppDomain object is unloaded. The HostManagerActivityProvider class does not make any checks and always creates a new assembly. That is why the used unmanaged memory grows constantly. This topic illustrates how to implement a custom HostManagerActivityProvider class that does not require additional memory, but does not allow reusing runtime activities.

Tip

Alternatively, you can raise the RefreshWorkflowDefinitionsService.DelayPeriod value to an hour (see Workflow Server Service), and manually force the refresh operation when necessary.

Note

ASP.NET Core Blazor applications do not support the Workflow Module.

WWF and WCF will not be ported to .NET Core/.NET 6+ by Microsoft. We recommend that you implement Controllers or custom solutions such as Hangfire, Quartz.NET, and others for former Workflow Module scenarios. To save your time, consider this free module within the eXpand Framework.

  • Add the following class to the Workflow Server Service project.

    using System.IO;
    using System.Activities;
    using System.Activities.XamlIntegration;
    using DevExpress.ExpressApp.Workflow;
    using DevExpress.ExpressApp.Workflow.Server;
    using DevExpress.ExpressApp.Workflow.CommonServices;
    // ...
    public class CustomHostManagerActivityProvider : DevExpress.ExpressApp.Workflow.Server.WorkflowServerService {
        private void Manager_HostOpening(object sender, EventArgs e) {
            IList<IWorkflowDefinition> definitions = 
                GetService<IWorkflowDefinitionProvider>().GetDefinitions();
            Dictionary<string, Activity> activities = new Dictionary<string, Activity>();
            foreach(IWorkflowDefinition definition in definitions) {
                if(definition.CanOpenHost) {
                    Activity activity = ActivityXamlServices.Load(new StringReader(definition.Xaml));
                    activity.DisplayName = definition.GetActivityTypeName();
                    activities.Add(definition.GetUniqueId(), activity);
                }
            }
            HostManager.RefreshHosts(activities);
        }
        protected override void OnInitialized() {
            base.OnInitialized();
            HostManager.HostsOpening += Manager_HostOpening;
        }
    }
    
  • Open the WorkflowServerService.cs (WorkflowServerService.vb) file. In the OnStart method, assign an instance of the CustomHostManagerActivityProvider class to the WorkflowServer.HostManagerActivityProvider property.

    server = new WorkflowServer("http://localhost:46232", objectSpaceProvider, objectSpaceProvider);
    server.HostManagerActivityProvider = new CustomHostManagerActivityProvider();
    
See Also