2017-05-18 4 views
3

실패한 경우 여러 작업 중 하나를 다시 시작하려고합니다. 임 HandleException(t) 메서드는 excisting 작업의 배열에서 작업을 찾아 그 자리에 새로운 것을 만들어야하는 .ContinueWith(t => { HandleException(t); }, TaskContinuationOptions.OnlyOnFaulted);을 사용합니다. 내 HandleException(t) 메서드에 전달 된 작업 만 원래 작업과 다르므로 내 발췌 작업에서 찾을 수 없습니다. 또한 excisting 작업은 예외가 처리되는 시점에 실행 중입니다.실패한 작업 다시 시작

예 :에

using System; 
using System.Threading.Tasks; 
using System.Threading; 

static Task[] tasks; 
static void Main(string[] args) 
{ 
    tasks = new Task[2]; 
    for (int i = 0; i < tasks.Count(); i++) 
    { 
     tasks[i] = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM"); }) 
      .ContinueWith(t => { HandleException(t); } 
      , TaskContinuationOptions.OnlyOnFaulted); 

     Console.WriteLine(String.Format("Task {0} started", tasks[i].Id)); 
    } 

    Console.ReadLine(); 
} 

static void HandleException(Task task) 
{ 
    Console.WriteLine(String.Format("Task {0} stopped", task.Id)); 

    // Check task status 
    for (int i = 0; i < tasks.Count(); i++) 
    { 
     Console.WriteLine(String.Format("Task {0} status = {1}", i, tasks[i].Status)); 
    } 
    // fFind and restart the task here 
    if (tasks.Contains(task)) 
    { 
     int index = Array.IndexOf(tasks, task); 
     tasks[index] = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM"); }) 
     .ContinueWith(t => { HandleException(t); } 
     , TaskContinuationOptions.OnlyOnFaulted); 

     Console.WriteLine(String.Format("Task {0} started", tasks[index].Id)); 
    } 
} 

내 응용 프로그램 결과 :

Task 3 started 
Task 6 started 
Task 5 stopped 
Task 0 status = Running 
Task 2 stopped 
Task 1 status = Running 
Task 0 status = Running 
Task 1 status = Running 

HandleException(t)에 전달되는 작업이 원래 작업 다르기 때문에

, 그것은 따라서 tasks[]하지에없는 다시 시작되었습니다. 또한 tasks[]의 상태를 보면 아직 멈추지 않았습니다. 작업을 올바르게 다시 시작하려면 어떻게해야합니까?

답변

4

연속 작업을 원래 작업이 아닌 어레이에 저장했기 때문에 결과가 ContinueWith입니다. 수정하려면 원래 작업을 저장하십시오.

var task = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM");}); 
task.ContinueWith(t => { HandleException(t); } 
     , TaskContinuationOptions.OnlyOnFaulted); 
tasks[i] = task; 
+0

정말 대단한 문제였습니다. 또한 작업 상태가 수정되었습니다. – MrEighteen

+0

@Evk HandleException (t)가 재귀 호출이므로 결국 스택 오버플로가 발생하지 않습니까? –

+1

@MaximPodkolzin no는 모두 다른 스레드에서 발생하기 때문입니다. 'Task.Run'을 통해 새 작업이 시작됩니다. 스레드 풀에서 스레드를 가져옵니다> 예외가 throw됩니다.> 다른 스레드에서 HandleException이 다시 호출됩니다.>'Task.Run'이 다시 호출되고 다른 스레드가 스레드 풀에서 HandleException을 실행 중이다. 왜냐하면 현재 스레드가 실행을 끝내고 다시 풀로 돌아 간다. 스택 오버플로를 위해 동일한 스레드가 재귀 적으로 함수를 실행해야하지만 여기에서는 서로 다른 스레드 (다른 스택)를 사용합니다. – Evk

관련 문제