나는 장기 실행, 블로킹, 불안정 및 \ 또는 영원히 걸릴 가능성이있는 별도의 스레드에서 코드를 실행해야하는 경우가 많습니다. TPL의 존재 이후 인터넷은 취소 토큰을 사용하여 작업을 멋지게 취소하는 예제로 가득차 있지만 중단 된 작업을 죽이는 예제는 발견하지 못했습니다. 영원히 중단되는 코드는 하드웨어와 통신하거나 제 3 자 코드를 호출하자 마자 예상됩니다. 중단 된 작업은 취소 토큰을 확인할 수 없으며 영원히 살아 남을 운명입니다. 중요한 어플리케이션에서 나는 정기적 인 시간 간격으로 보내지는 살아있는 신호로 작업을 준비한다. 걸려있는 작업이 감지 되 자마자 작업이 중단되고 새 인스턴스가 시작됩니다.매달린 작업을 보장하는 방법이 보장 되었습니까?
아래 코드는 영원히 멈출 가능성이있는 장기 실행 자리 표시 자 메서드 SomeThirdPartyLongOperation()을 호출하는 예제 작업을 보여줍니다. StopTask()는 작업이 아직 실행 중인지 여부를 먼저 확인하여 해지 토큰을 사용하여 작업을 취소하려고 시도합니다. 그래도 작동하지 않으면 작업이 중단되고 기본 스레드가 중단되어 \ 중단 된 이전 학교 스타일이됩니다.
private Task _task;
private Thread _thread;
private CancellationTokenSource _cancellationTokenSource;
public void StartTask()
{
_cancellationTokenSource = new CancellationTokenSource();
_task = Task.Factory.StartNew(() => DoWork(_cancellationTokenSource.Token), _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
public void StopTask()
{
if (_task.Status == TaskStatus.RanToCompletion)
return;
_cancellationTokenSource.Cancel();
try
{
_task.Wait(2000); // Wait for task to end and prevent hanging by timeout.
}
catch (AggregateException aggEx)
{
List<Exception> exceptions = aggEx.InnerExceptions.Where(e => !(e is TaskCanceledException)).ToList(); // Ignore TaskCanceledException
foreach (Exception ex in exceptions)
{
// Process exception thrown by task
}
}
if (!_task.IsCompleted) // Task hangs and didn't respond to cancellation token => old school thread abort
{
_thread.Interrupt();
if (!_thread.Join(2000))
{
_thread.Abort();
}
}
_cancellationTokenSource.Dispose();
if (_task.IsCompleted)
{
_task.Dispose();
}
}
private void DoWork(CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(Thread.CurrentThread.Name)) // Set thread name for debugging
Thread.CurrentThread.Name = "DemoThread";
_thread = Thread.CurrentThread; // Save for interrupting/aborting if thread hangs
for (int i = 0; i < 10; i++)
{
cancellationToken.ThrowIfCancellationRequested();
SomeThirdPartyLongOperation(i);
}
}
몇 년 동안이 구조를 사용해 왔지만 몇 가지 잠재적 인 실수가 있는지 알고 싶습니다. 기본 스레드를 저장하거나 디버깅을 단순화하는 이름을 제공하는 태스크의 예는 본 적이 없으므로 이것이 올바른 방향인지 확실하지 않습니다. 어떤 세부 사항든지에 코멘트는 환영 받다!
의견을 보내 주셔서 감사합니다. 자신의 신뢰할 수있는 영역을 떠나서 일부 타사 소프트웨어를 통합하자 마자 가끔이 소프트웨어가 멈추는 현실 세계가 _ 있습니다. 별도의 스레드에서이 소프트웨어를 실행하면 주 소프트웨어에 타사 소프트웨어에 대한 추가 제어 권한을 부여 할 수 있습니다. 스레드 풀에서 다른 스레드가 할당 될 수 있음을 알고 있지만 코드에 대기 중이므로이 작업이 LongRunning이며 따라서 전용 스레드 [link] (https://coderkarl.wordpress.com)에 할당되었음을 알고 있습니다./2012/12/13/long-running-tasks-and-threads /) –