# Thread management (/en/realtime-media/im/build/build-groups-rooms-and-threads/threading/thread-management/windows)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Threads enable users to create a separate conversation from a specific message within a chat group to keep the main chat uncluttered.

The following illustration shows the implementation of creating a thread, a conversation in a thread, and the operations you can perform in a thread.

![1655176216910](https://web-cdn.agora.io/docs-files/1655176216910)

![1655176932917](https://web-cdn.agora.io/docs-files/1655176932917)

This page shows how to use the Chat SDK to create and manage threads in your app.

## Understand the tech

The Chat SDK for Windows provides the `IChatThreadManager`, `ChatThread`, `ChatThreadEvent`, and `IChatThreadManagerDelegate` classes for thread management, which allow you to implement the following features:

## Prerequisites

Before proceeding, ensure that you meet the following requirements:

* You have initialized the Chat SDK. For details, see [SDK quickstart](../../../get-started-sdk).
* You understand the call frequency limit of the Chat APIs supported by different pricing plans as described in [Limitations](../../limitations).

<CalloutContainer type="info">
  <CalloutDescription>
    The thread feature is supported by all types of [Pricing Plans](../../../reference/pricing-plan-details) and is enabled by default once you have enabled Chat in [Agora Console](https://console.agora.io/).
  </CalloutDescription>
</CalloutContainer>

## Implementation

This section describes how to call the APIs provided by the Chat SDK to implement thread features.

### Create a thread

All chat group members can call `CreateThread` to create a thread from a specific message in a chat group.

Once a thread is created in a chat group, all chat group members receive the `IChatThreadManagerDelegate#OnCreateThread` callback. In a multi-device use-case, all the other devices receive the `IMultiDeviceDelegate#onThreadMultiDevicesEvent` callback triggered by the `THREAD_CREATE` event.

The following sample code shows how to create a thread in a chat group:

```csharp
SDKClient.Instance.ThreadManager.CreateThread(threadName, msgId, groupid, new ValueCallBack(
    onSuccess: (thread) =>
    {
        DebugLog($"CreateThread success");
        if (null != thread)
        {
            // Handles the returned thread object
        }
    },
    onError: (code, desc) =>
    {
        Debug.Log($"CreateThread failed, code:{code}, desc:{desc}");
    }
));
```

### Destroy a thread

Only the chat group owner and admins can call `DestroyThread` to disband a thread in a chat group.

Once a thread is disbanded, all chat group members receive the `IChatThreadManagerDelegate#onThreadNotifyChange` callback. In a multi-device use-case, all the other devices receive the `IMultiDeviceDelegate#onThreadMultiDevicesEvent` callback triggered by the `THREAD_DESTROY` event.

<CalloutContainer type="info">
  <CalloutDescription>
    Once a thread is destroyed or the chat group where a thread resides is destroyed, all data of the thread is deleted from the local database and memory.
  </CalloutDescription>
</CalloutContainer>

The following sample code shows how to destroy a thread:

```csharp
SDKClient.Instance.ThreadManager.DestroyThread(tid, new CallBack(
    onSuccess: () =>
    {
        Debug.Log($"DestroyThread success");
    },
    onError: (code, desc) =>
    {
        Debug.Log($"DestroyThread failed, code:{code}, desc:{desc}");
    }
));
```

### Join a thread

All chat group members can call `JoinThread` to join a thread as follows:

1. Retrieve the thread ID from the `IChatThreadManagerDelegate#OnCreateThread` or `IChatThreadManagerDelegate#onThreadNotifyChange` callback. Or retrieve the thread list in a chat group by calling `FetchThreadListOfGroup`, and locate the ID of the thread that you want to join.
2. Call `JoinThread` to pass in the thread ID and join the specified thread.

In a multi-device use-case, all the other devices receive the `IMultiDeviceDelegate#onThreadMultiDevicesEvent` callback triggered by the `THREAD_JOIN` event.

The following sample code shows how to join a thread:

```csharp
SDKClient.Instance.ThreadManager.JoinThread(tid, new ValueCallBack(
    onSuccess: (thread) =>
    {
        Debug.Log($"JoinThread success");
        if (null != thread)
        {
           // Handles the returned thread object
        }
    },
    onError: (code, desc) =>
    {
        Debug.Log($"JoinThread failed, code:{code}, desc:{desc}");
    }
));
```

### Leave a thread

All thread members can call `LeaveThread` to leave a thread. Once a member leaves a thread, they can no longer receive the thread messages.

In a multi-device use-case, all the other devices receive the `IMultiDeviceDelegate#onThreadMultiDevicesEvent` callback triggered by the `THREAD_LEAVE` event.

The following sample code shows how to leave a thread:

```csharp
SDKClient.Instance.ThreadManager.LeaveThread(tid, new CallBack(
    onSuccess: () =>
    {
        Debug.Log($"LeaveThread success");
    },
    onError: (code, desc) =>
    {
        Debug.Log($"LeaveThread failed, code:{code}, desc:{desc}");
    }
));
```

### Remove a member from a thread

Only the chat group owner and admins can call `RemoveThreadMember` to remove the specified member from a thread.

Once a member is removed from a thread, they receive the `IChatThreadManagerDelegate#OnUserKickOutOfChatThread` callback and can no longer receive the thread messages. In a multi-device use-case, all the other devices receive the `IMultiDeviceDelegate#onThreadMultiDevicesEvent` callback triggered by the `THREAD_KICK` event.

The following sample code shows how to remove a member from a thread:

```csharp
SDKClient.Instance.ThreadManager.RemoveThreadMember(tid, uname, new CallBack(
    onSuccess: () =>
    {
        Debug.Log($"RemoveThreadMember success");
    },
    onError: (code, desc) =>
    {
        Debug.Log($"RemoveThreadMember failed, code:{code}, desc:{desc}");
    }
));
```

### Update the name of a thread

Only the chat group owner, chat group admins, and thread creator can call `ChangeThreadSubject` to update a thread name.

Once a thread name is updated, all chat group members receive the `IChatThreadManagerDelegate#OnChatThreadUpdate` callback. In a multi-device use-case, all the other devices receive the `IMultiDeviceDelegate#onThreadMultiDevicesEvent` callback triggered by the `THREAD_UPDATE` event.

The following sample code shows how to update a thread name:

```csharp
SDKClient.Instance.ThreadManager.ChangeThreadSubject(tid, subject, new CallBack(
    onSuccess: () =>
    {
        Debug.Log($"ChangeThreadSubject success");
    },
    onError: (code, desc) =>
    {
        Debug.Log($"ChangeThreadSubject failed, code:{code}, desc:{desc}");
    }
));
```

### Retrieve the attributes of a thread

All chat group members can call `GetThreadDetail` to retrieve the thread attributes from the server.

The following sample code shows how to retrieve the thread attributes:

```csharp
SDKClient.Instance.ThreadManager.GetThreadDetail(tid, new ValueCallBack(
        onSuccess: (thread) =>
        {
            Debug.Log($"GetThreadDetail success");
            if (null != thread)
            {
                //Add thread handling here
            }
        },
        onError: (code, desc) =>
        {
            Debug.Log($"GetThreadDetail failed, code:{code}, desc:{desc}");
        }
    ));
```

### Retrieve the member list of a thread

All chat group members can call `FetchThreadMembers` to retrieve a paginated member list of a thread from the server, as shown in the following sample code:

```csharp
SDKClient.Instance.ThreadManager.FetchThreadMembers(tid, cursor, page_size, new ValueCallBack>(
    onSuccess: (cursor_result) =>
    {
        Debug.Log($"FetchThreadMembers success");
        if(null != cursor_result)
        {
            // Handles the returned results
        }
    },
    onError: (code, desc) =>
    {
        Debug.Log($"FetchThreadMembers failed, code:{code}, desc:{desc}");
    }
));
```

### Retrieve a thread list

Users can call `FetchMineJoinedThreadList` to retrieve a paginated list from the server of all the threads they have created and joined, as shown in the following sample code:

```csharp
 SDKClient.Instance.ThreadManager.FetchMineJoinedThreadList(cursor, page_size, new ValueCallBack>(
    onSuccess: (cursor_result) =>
    {
        Debug.Log($"FetchMineJoinedThreadList success");
        if (null != cursor_result)
        {
            // Handles the returned thread list in cursor_result.Data
        }
    },
    onError: (code, desc) =>
    {
        Debug.Log($"FetchMineJoinedThreadList failed, code:{code}, desc:{desc}");
    }
));
```

Besides, users can call `FetchThreadListOfGroup` to retrieve a paginated list from the server of all the threads in a specified chat group, as shown in the following sample code:

```csharp
SDKClient.Instance.ThreadManager.FetchThreadListOfGroup(tid, joined, cursor, page_size, new ValueCallBack>(
    onSuccess: (cursor_result) =>
    {
        Debug.Log($"FetchThreadListOfGroup success");
        if (null != cursor_result)
        {
            // Handles the returned thread list in cursor_result.Data
        }
    },
    onError: (code, desc) =>
    {
        Debug.Log($"FetchThreadListOfGroup failed, code:{code}, desc:{desc}");
    }
));
```

### Retrieve the latest message from multiple threads

Users can call `GetLastMessageAccordingThreads` to retrieve the latest message from multiple threads.

The following sample code shows how to retrieve the latest message from multiple threads:

```csharp
SDKClient.Instance.ThreadManager.GetLastMessageAccordingThreads(threadIds, new ValueCallBack>(
    onSuccess: (dict) =>
    {
        Debug.Log($"GetLastMessageAccordingThreads success");
        foreach (var it in dict)
        {
            // Iterates through the threads to handle the newest message in each thread
        }
    },
    onError: (code, desc) =>
    {
        Debug.Log($"GetLastMessageAccordingThreads failed, code:{code}, desc:{desc}");
    }
));
```

### Listen for thread events

To monitor thread events, users can listen for the callbacks in the `IChatThreadManagerDelegate` class and add app logics accordingly. If a user wants to stop listening for the callbacks, make sure that the user removes the listener to prevent memory leakage.

Refer to the following sample code to listen for thread events:

```csharp
class ThreadManagerDelegate : IChatThreadManagerDelegate
{
    public void OnChatThreadCreate(ChatThreadEvent threadEvent)
    {
    }
    public void OnChatThreadUpdate(ChatThreadEvent threadEvent)
    {
    }
    public void OnChatThreadDestroy(ChatThreadEvent threadEvent)
    {
    }
    public void OnUserKickOutOfChatThread(ChatThreadEvent threadEvent)
    {
    }
}
// Registers the event listener
IChatThreadManagerDelegate threadManagerDelegate = new ThreadManagerDelegate();
SDKClient.Instance.ThreadManager.AddThreadManagerDelegate(threadManagerDelegate);
// Removes the event listener
SDKClient.Instance.ThreadManager.RemoveThreadManagerDelegate(threadManagerDelegate);
```

    
  
      
  
      
  
