Skip to Content

Prozess starten

Mit dem ProcessDefinitionsClient können Prozess-Instanzen gestartet werden. Es gibt zwei Hauptmethoden: synchrones Starten und Starten mit Warten auf Prozess-Ende.

StartProcessInstanceAsync()

Startet eine neue Prozess-Instanz:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var response = await client.StartProcessInstanceAsync( processModelId: "OrderProcess", startEventId: "StartEvent_1", initialToken: new { orderId = "ORD-12345", amount = 1500.00 } ); Console.WriteLine($"Prozess gestartet: {response.ProcessInstanceId}"); Console.WriteLine($"Correlation-ID: {response.CorrelationId}");

Parameter

ParameterTypBeschreibung
processModelIdstringID des Prozessmodells
startEventIdstringID des Start-Events im BPMN
initialTokenobjectPayload/Daten für den Prozess (optional)
correlationIdstringEigene Correlation-ID (optional)

Mit typisiertem Payload

Verwenden Sie C# Records für type-safe Payloads:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); // Payload als Record definieren var payload = new OrderPayload( OrderId: "ORD-12345", CustomerName: "Max Mustermann", Amount: 1500.00m, Currency: "EUR" ); var response = await client.StartProcessInstanceAsync( processModelId: "OrderProcess", startEventId: "StartEvent_1", initialToken: payload ); Console.WriteLine($"Order-Prozess gestartet: {response.ProcessInstanceId}"); // Payload-Definition internal sealed record OrderPayload( string OrderId, string CustomerName, decimal Amount, string Currency );

Best Practice: Verwenden Sie C# Records für Payloads. Dies bietet Type Safety, IntelliSense-Unterstützung und macht den Code lesbarer.

Mit eigener Correlation-ID

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); // Eigene Correlation-ID generieren var correlationId = Guid.NewGuid().ToString(); var payload = new PaymentPayload( PaymentId: "PAY-789", Amount: 250.00m ); var response = await client.StartProcessInstanceAsync( processModelId: "PaymentProcess", startEventId: "StartEvent_1", initialToken: payload, correlationId: correlationId ); Console.WriteLine($"Prozess gestartet mit Correlation-ID: {correlationId}"); Console.WriteLine($"ProcessInstance-ID: {response.ProcessInstanceId}"); // Payload-Definition internal sealed record PaymentPayload( string PaymentId, decimal Amount );

Eine Correlation-ID ermöglicht es, mehrere Prozess-Instanzen logisch zu gruppieren und später gemeinsam abzufragen.

StartAndAwaitEndAsync()

Startet einen Prozess und wartet auf dessen Beendigung:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var payload = new CalculationPayload( NumberA: 10, NumberB: 20 ); Console.WriteLine("Starte Prozess und warte auf Ergebnis..."); // Startet und wartet bis der Prozess fertig ist var result = await client.StartAndAwaitEndAsync( processModelId: "CalculationProcess", startEventId: "StartEvent_1", initialToken: payload ); Console.WriteLine($"Prozess beendet: {result.ProcessInstanceId}"); Console.WriteLine($"State: {result.State}"); // End-Token auswerten if (result.EndToken != null) { var output = result.EndToken.GetPayload<CalculationResult>(); Console.WriteLine($"Ergebnis: {output.Result}"); } // Payload-Definitionen internal sealed record CalculationPayload(int NumberA, int NumberB); internal sealed record CalculationResult(int Result);

StartAndAwaitEndAsync() blockiert, bis der Prozess beendet ist. Verwenden Sie diese Methode nur für kurz laufende Prozesse oder mit einem Timeout.

Mit Timeout

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var payload = new DataProcessingPayload( Data: "sample-data" ); // CancellationToken mit Timeout erstellen using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); try { var result = await client.StartAndAwaitEndAsync( processModelId: "DataProcessing", startEventId: "StartEvent_1", initialToken: payload, cancellationToken: cts.Token ); Console.WriteLine($"Prozess erfolgreich beendet: {result.ProcessInstanceId}"); } catch (OperationCanceledException) { Console.WriteLine("Timeout: Prozess dauert länger als 30 Sekunden"); } internal sealed record DataProcessingPayload(string Data);

Mehrere Prozesse parallel starten

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var orders = new[] { new OrderPayload("ORD-001", "Alice", 100.00m), new OrderPayload("ORD-002", "Bob", 200.00m), new OrderPayload("ORD-003", "Charlie", 150.00m) }; Console.WriteLine($"Starte {orders.Length} Prozesse parallel..."); // Alle Prozesse parallel starten var startTasks = orders.Select(order => client.StartProcessInstanceAsync( processModelId: "OrderProcess", startEventId: "StartEvent_1", initialToken: order ) ).ToArray(); // Auf alle warten var responses = await Task.WhenAll(startTasks); Console.WriteLine($"Alle {responses.Length} Prozesse gestartet:"); foreach (var response in responses) { Console.WriteLine($" - {response.ProcessInstanceId}"); } internal sealed record OrderPayload( string OrderId, string CustomerName, decimal Amount );

Start-Event ermitteln

Wenn Sie die Start-Event-ID nicht kennen:

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var processModelId = "OrderProcess"; // Prozessmodell abrufen var processes = await client.GetProcessModelsAsync(); var process = processes.FirstOrDefault(p => p.Id == processModelId); if (process == null) { Console.WriteLine($"Prozess '{processModelId}' nicht gefunden"); return; } // Erstes Start-Event verwenden var startEvent = process.StartEvents.FirstOrDefault(); if (startEvent == null) { Console.WriteLine("Kein Start-Event gefunden"); return; } Console.WriteLine($"Verwende Start-Event: {startEvent.Id}"); // Prozess starten var payload = new OrderPayload("ORD-789", "Max Mustermann", 500.00m); var response = await client.StartProcessInstanceAsync( processModelId: processModelId, startEventId: startEvent.Id, initialToken: payload ); Console.WriteLine($"Prozess gestartet: {response.ProcessInstanceId}"); internal sealed record OrderPayload( string OrderId, string CustomerName, decimal Amount );

Prozess mit Message Start Event

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); // Für Message Start Events var payload = new OrderReceivedPayload( OrderId: "ORD-456", Source: "WebShop" ); var response = await client.StartProcessInstanceAsync( processModelId: "OrderProcessing", startEventId: "MessageStartEvent_OrderReceived", initialToken: payload ); Console.WriteLine($"Prozess via Message Event gestartet: {response.ProcessInstanceId}"); internal sealed record OrderReceivedPayload( string OrderId, string Source );

Mit Authentifizierung

using ProcessCube.Engine; using ProcessCube.Engine.Client.Identity; // Identity Provider erstellen var identityProvider = new ClientCredentialsIdentityProvider( authorityAddress: "http://localhost:11235", clientId: "order-service", clientSecret: "secret-key", scope: "engine_write" ); // Token abrufen var identity = await identityProvider.GetIdentityAsync(); // Client mit Identity erstellen var client = ClientFactory.CreateProcessDefinitionsClient( engineAddress: "http://localhost:8000", identity: identity ); // Prozess starten (authentifiziert) var payload = new OrderPayload("ORD-999", "Alice", 750.00m); var response = await client.StartProcessInstanceAsync( processModelId: "OrderProcess", startEventId: "StartEvent_1", initialToken: payload ); Console.WriteLine($"Authenticated start: {response.ProcessInstanceId}"); internal sealed record OrderPayload( string OrderId, string CustomerName, decimal Amount );

Response Properties

Die StartProcessInstanceResponse enthält:

PropertyTypBeschreibung
ProcessInstanceIdstringEindeutige ID der Prozess-Instanz
CorrelationIdstringCorrelation-ID der Instanz
ProcessModelIdstringID des Prozessmodells
StartEventIdstringID des verwendeten Start-Events
EndTokenTokenToken am Prozess-Ende (nur bei StartAndAwaitEndAsync)

Fehlerbehandlung

using ProcessCube.Engine; using ProcessCube.Engine.Client.Exceptions; var engineAddress = "http://localhost:8000"; var client = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var payload = new OrderPayload("ORD-123", "Max", 100.00m); try { var response = await client.StartProcessInstanceAsync( processModelId: "OrderProcess", startEventId: "StartEvent_1", initialToken: payload ); Console.WriteLine($"Prozess gestartet: {response.ProcessInstanceId}"); } catch (EngineClientException ex) when (ex.StatusCode == 404) { Console.WriteLine("Prozess oder Start-Event nicht gefunden"); Console.WriteLine($"Details: {ex.Message}"); } catch (EngineClientException ex) when (ex.StatusCode == 400) { Console.WriteLine("Ungültiger Payload"); Console.WriteLine($"Details: {ex.Message}"); } catch (EngineClientException ex) when (ex.StatusCode == 401) { Console.WriteLine("Nicht authentifiziert"); } catch (EngineClientException ex) when (ex.StatusCode == 403) { Console.WriteLine("Fehlende Berechtigung zum Starten"); } catch (HttpRequestException ex) { Console.WriteLine($"Verbindungsfehler: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Unerwarteter Fehler: {ex.Message}"); } internal sealed record OrderPayload( string OrderId, string CustomerName, decimal Amount );

Prozess starten und Status überwachen

using ProcessCube.Engine; var engineAddress = "http://localhost:8000"; var definitionsClient = ClientFactory.CreateProcessDefinitionsClient(engineAddress); var instancesClient = ClientFactory.CreateProcessInstancesClient(engineAddress); // Prozess starten var payload = new ApprovalPayload( RequestId: "REQ-456", Amount: 10000.00m ); var response = await definitionsClient.StartProcessInstanceAsync( processModelId: "ApprovalProcess", startEventId: "StartEvent_1", initialToken: payload ); var processInstanceId = response.ProcessInstanceId; Console.WriteLine($"Approval-Prozess gestartet: {processInstanceId}"); // Status überwachen while (true) { await Task.Delay(2000); // 2 Sekunden warten var instances = await instancesClient.QueryAsync(query => { query.FilterByProcessInstanceId(processInstanceId); }); var instance = instances.SingleOrDefault(); if (instance == null) { Console.WriteLine("Prozess nicht gefunden"); break; } Console.WriteLine($"Status: {instance.State}"); if (instance.State == ProcessState.Finished) { Console.WriteLine("Prozess erfolgreich abgeschlossen"); break; } else if (instance.State == ProcessState.Error) { Console.WriteLine("Prozess mit Fehler beendet"); break; } else if (instance.State == ProcessState.Terminated) { Console.WriteLine("Prozess wurde abgebrochen"); break; } } internal sealed record ApprovalPayload( string RequestId, decimal Amount );

ASP.NET Core Integration

using Microsoft.AspNetCore.Mvc; using ProcessCube.Engine; [ApiController] [Route("api/[controller]")] public class OrderController : ControllerBase { private readonly IProcessDefinitionsClient _client; public OrderController(IProcessDefinitionsClient client) { _client = client; } [HttpPost] public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request) { var payload = new OrderPayload( request.OrderId, request.CustomerName, request.Amount ); try { var response = await _client.StartProcessInstanceAsync( processModelId: "OrderProcess", startEventId: "StartEvent_1", initialToken: payload ); return Ok(new { processInstanceId = response.ProcessInstanceId, correlationId = response.CorrelationId, message = "Order process started successfully" }); } catch (EngineClientException ex) { return StatusCode((int)ex.StatusCode, new { error = ex.Message }); } } } public record CreateOrderRequest( string OrderId, string CustomerName, decimal Amount ); internal sealed record OrderPayload( string OrderId, string CustomerName, decimal Amount );

Performance-Tipp: Für viele Prozess-Starts verwenden Sie Task.WhenAll() für parallele Ausführung, anstatt sequenziell zu starten.

Nächste Schritte