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
| Parameter | Typ | Beschreibung |
|---|---|---|
processModelId | string | ID des Prozessmodells |
startEventId | string | ID des Start-Events im BPMN |
initialToken | object | Payload/Daten für den Prozess (optional) |
correlationId | string | Eigene 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:
| Property | Typ | Beschreibung |
|---|---|---|
ProcessInstanceId | string | Eindeutige ID der Prozess-Instanz |
CorrelationId | string | Correlation-ID der Instanz |
ProcessModelId | string | ID des Prozessmodells |
StartEventId | string | ID des verwendeten Start-Events |
EndToken | Token | Token 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
- Prozess-Instanzen abfragen - Gestartete Prozesse finden
- Prozess beenden - Instanzen abbrechen
- User Tasks - User Tasks in Prozessen bearbeiten
- External Tasks - External Tasks verarbeiten