네, 여러 비동기 작업을 동시에 수행하면서 특정 작업만 멈추는 방법에 대해 설명드리겠습니다. 이를 구현하기 위해 각 작업별로 고유한 식별자를 사용하고, 작업별로 `CancellationTokenSource`를 관리하는 방식을 사용할 수 있습니다.
다음은 이를 구현한 예시 코드입니다:
```csharp
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class TaskController : ControllerBase
{
private static readonly ConcurrentDictionary<string, CancellationTokenSource> _tasks = new ConcurrentDictionary<string, CancellationTokenSource>();
[HttpPost("start")]
public async Task<IActionResult> StartTask([FromBody] TaskRequest request)
{
var taskId = Guid.NewGuid().ToString();
var cts = new CancellationTokenSource();
if (_tasks.TryAdd(taskId, cts))
{
// 비동기로 작업 시작
_ = RunLongTask(taskId, request.TaskType, cts.Token);
return Ok(new { TaskId = taskId, Message = "작업이 시작되었습니다." });
}
return BadRequest("작업을 시작할 수 없습니다.");
}
[HttpPost("stop/{taskId}")]
public IActionResult StopTask(string taskId)
{
if (_tasks.TryRemove(taskId, out var cts))
{
cts.Cancel();
return Ok($"작업 {taskId}가 중지되었습니다.");
}
return NotFound($"작업 {taskId}를 찾을 수 없습니다.");
}
private async Task RunLongTask(string taskId, string taskType, CancellationToken cancellationToken)
{
try
{
Console.WriteLine($"작업 {taskId} ({taskType}) 시작됨");
while (!cancellationToken.IsCancellationRequested)
{
// 실제 작업 수행
await Task.Delay(1000, cancellationToken);
Console.WriteLine($"작업 {taskId} ({taskType}) 실행 중...");
}
}
catch (OperationCanceledException)
{
Console.WriteLine($"작업 {taskId} ({taskType}) 취소됨");
}
finally
{
_tasks.TryRemove(taskId, out _);
Console.WriteLine($"작업 {taskId} ({taskType}) 종료됨");
}
}
}
public class TaskRequest
{
public string TaskType { get; set; }
}
```
이 구현의 주요 특징은 다음과 같습니다:
1. `ConcurrentDictionary`를 사용하여 여러 작업의 `CancellationTokenSource`를 관리합니다. 키는 작업의 고유 ID입니다.
2. `StartTask` API:
- 새로운 GUID를 생성하여 작업 ID로 사용합니다.
- 새 `CancellationTokenSource`를 생성하고 딕셔너리에 추가합니다.
- 비동기 작업을 시작하고 작업 ID를 반환합니다.
3. `StopTask` API:
- 주어진 작업 ID에 해당하는 `CancellationTokenSource`를 찾아 취소합니다.
- 작업이 존재하지 않으면 NotFound를 반환합니다.
4. `RunLongTask` 메서드:
- 실제 장기 실행 작업을 시뮬레이션합니다.
- 취소 토큰을 주기적으로 확인하여 작업 취소 요청을 처리합니다.
- 작업이 완료되거나 취소되면 딕셔너리에서 해당 작업을 제거합니다.
이 방식을 사용하면 여러 비동기 작업을 동시에 실행하고 각각을 개별적으로 관리할 수 있습니다. 클라이언트는 시작 API를 호출하여 작업 ID를 받고, 이 ID를 사용하여 나중에 특정 작업만 중지할 수 있습니다.
실제 사용 시 고려할 사항:
1. 에러 처리를 더 강화하세요.
2. 작업 상태 모니터링 기능을 추가하는 것이 좋습니다.
3. 장기 실행 작업의 결과를 저장하고 검색하는 메커니즘을 구현하세요.
4. 보안 측면에서 작업 ID의 유효성을 검증하는 로직을 추가하세요.
이 구현에 대해 더 자세한 설명이 필요하거나 특정 부분에 대해 질문이 있으시면 말씀해 주세요.
카테고리 없음