# Send Command (/sdks/csharp/tutorials/command-send)



## Overview [#overview]

A **command** is KubeMQ's fire-and-confirm RPC pattern: you reach for it when you need to know that an action actually ran on the other end — "restart-service" — but you don't need any data back, just a yes/no on execution. It's the middle ground between one-way pub/sub, where you get no confirmation at all, and a query, where the handler returns a result payload. Commands turn "I hope that worked" into a definite outcome your caller can branch on.

This sample builds that lesson: `client.SendCommandAsync(new CommandMessage { ... })` sends the request and blocks until the handler calls `SendCommandResponseAsync` or `TimeoutInSeconds` elapses — the response's `Executed` and `Error` fields tell you exactly what happened.

**Gotchas:** if no handler is subscribed (or it's still starting up), `SendCommandAsync` waits out the full `TimeoutInSeconds` before failing — there's no fast "nobody's listening" error. A timeout can surface as either a `KubeMQTimeoutException` or an `KubeMQOperationException` whose message mentions "timeout," so handle both. And a command's response carries no business data — if you need the handler to return a value, use a query instead.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* C# SDK installed (`dotnet add package KubeMQ.SDK.CSharp`)

## Code [#code]

```csharp title="Program.cs"
// KubeMQ .NET SDK — Commands: Send Command
//
// This example demonstrates sending a command and waiting for execution confirmation.
// Commands are request/reply: the sender waits for the handler to respond.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - Run Commands.HandleCommand in a separate terminal first
//   - dotnet run

using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Commands;
using KubeMQ.Sdk.Exceptions;
using System.Text;

await using var client = new KubeMQClient(new KubeMQClientOptions
{
    ClientId = "csharp-commands-send-command-client",
});
await client.ConnectAsync();

Console.WriteLine("Connected to KubeMQ server");

try
{
    var response = await client.SendCommandAsync(new CommandMessage
    {
        Channel = "csharp-commands.send-command",
        Body = Encoding.UTF8.GetBytes("restart-service"),
        TimeoutInSeconds = 10
    });

    Console.WriteLine($"Command executed: {response.Executed}");
    if (!string.IsNullOrEmpty(response.Error))
    {
        Console.WriteLine($"Error: {response.Error}");
    }
}
catch (KubeMQTimeoutException)
{
    Console.WriteLine("Command timed out — no handler responded within 10 seconds");
}
catch (KubeMQOperationException ex) when (ex.Message.Contains("timeout", StringComparison.OrdinalIgnoreCase))
{
    Console.WriteLine($"Command timed out — server reported: {ex.Message}");
}

Console.WriteLine("Done.");

// Expected output:
// Connected to KubeMQ server
// Command executed: True
// Done.

```

## How It Works [#how-it-works]

* `SendCommandAsync` sends the `CommandMessage` and blocks until the handler calls `SendCommandResponseAsync` or `TimeoutInSeconds` elapses.
* `TimeoutInSeconds` is the server-side wait window. The broker returns a timeout error after this interval if no handler responds.
* `KubeMQTimeoutException` is raised when the timeout fires — the second `catch` handles the edge case where the server returns a timeout inside an `OperationException` instead.
* Start the Handle Command example (`command-handle.mdx`) in a separate terminal first so the broker has a handler registered before this sender runs.

## Related [#related]

* [Pattern overview](/learn/rpc/getting-started)
* [C# SDK Reference](/sdks/csharp/reference)
* [Handle Command](/sdks/csharp/how-to/rpc/command-handle)
* [Command Timeout](/sdks/csharp/how-to/rpc/command-timeout)
