2015-01-03 3 views
1

다음과 같은 확장 프로그램을 사용하여 작업에 대한 시간 제한을 설정할 수 있습니다. 나는 내가 의도 한 결과를 얻을 다음을 사용하여 작업을 호출 할 때외부 메서드 호출시 작업 스케줄링

private async Task<string> TestTask(PageData page) 
{ 
    await Task.Delay(TimeSpan.FromSeconds(10)); 
    return "teststring"; 
} 

:

public static async Task<T> TimeoutAfter<T>(this Task<T> task, TimeSpan timeSpan, string message = null) 
{ 
    if (task == await Task.WhenAny(task, Task.Delay(timeSpan))) 
     return await task; 
    else 
    { 
     throw new TimeoutException(message); 
    } 
} 

나는 다음과 같은 작업을해야합니다. 나는 데 발행

var teststring = await TestTask() 
       .TimeoutAfter(TimeSpan.FromSeconds(5), "timeout message"); 

내가 (는 C++의 CLR 클래스 라이브러리이 경우) 외부 라이브러리의 메서드를 호출 할 때, TimeoutAfter 내부의 코드는()에 도달하지 못했다되고 작업이 시간 초과 적이 있다는 것입니다. Task.Factory.StartNew() (아래)를 사용하여이 문제를 해결할 수 있으며, 장기 실행 태스크에 콜백을 전달하고 주 태스크의 실행 전에 Task.Delay 태스크를 작성하지만이 작업은 확장으로 작동하지 않습니다. .

private async Task<T> Timeout<T>(Func<Task<T>> taskFunc) 
{ 
    var taskWait = Task.Delay(TimeSpan.FromSeconds(15)); 
    var task = Task.Factory.StartNew(() => taskFunc()); 

    if (task == await Task.WhenAny(task, taskWait)) 
     return await (await task); 
    else 
    { 
     throw new TimeoutException("timeout"); 
    } 
} 

TimeoutAfter()의 코드가 확장되는 작업에 특정 내용이있을 때만 실행되는 이유는 무엇입니까? 어떤 일이 발생하지 않도록 확장 프로그램에 어떤 기능을 추가 할 수 있습니까?

+1

당신은 혹시, 윈도우 폼이나 WPF UI에서이 일을하고 있는가? 문제를 보여주는 짧지 만 완전한 프로그램을 제작할 수 있습니까? 우리가 호출하는 메서드에 대해 아무것도 모르는 경우에는 도움이되지 않습니다 - 비동기입니까? # –

+1

이것은 전통적인 의미에서 실제로 "시간 초과"가 아니라는 것을 알고 있어야합니다. 작업이 중단되지 않고 대기 시간 만 종료됩니다. 작업이 계속 진행되며 무한 루프 또는 다른 장기 실행 작업 인 경우 매우 이상한 부작용이있을 수 있습니다. 타임 아웃 후에 그 태스크에 예외가 던져 질지도 모른다. –

+0

@JonSkeet 코드가 실행되고있는 콘솔 응용 프로그램에서 작업에서 호출되는 메서드는 C++ CLR 클래스 라이브러리에서 메서드를 호출하고 차례로 이미징 라이브러리와 연결된 외부 DLL을 호출합니다. 작업이 동기로 실행되고 확장이 호출되지 않는 특정 조건이 있습니까? – jimmyjambles

답변

-2

내 생각에 확장 방법을 시도 할 때 작업을 시작하지 않는다고 생각합니다.

Task은 완전히 비동기이며 코드는 must be started입니다. 작업을 시작하는 한 가지 방법은 공장에서 시도한 것처럼 StartNew를 사용하는 것입니다.

그러나 Start 메서드를 호출 할 수도 있습니다. 경고해야 할 것은 시작이 이미 시작되었거나 이미 끝난 경우 Start를 호출 할 때 예외가 발생한다는 것입니다.

그래서, 당신의 해결책이 될 수 있다고 생각 :

public static async Task<T> TimeoutAfter<T>(this Task<T> task, TimeSpan timeSpan, string message = null) 
{ 
    if(task.Status != TaskStatus.Running && task.Status != TaskStatus.RanToCompletion){ 
     task.Start(); 
    } 
    if (task == await Task.WhenAny(task, Task.Delay(timeSpan))) 
     return await task; 
    else 
    { 
     throw new TimeoutException(message); 
    } 
} 
+0

'Start '로 명시 적으로 async' 태스크를 시작할 필요가 없습니다. – i3arnon

+0

태스크에 대한 참조가 일단 시작되면, 문제는 특정 기본 태스크와 함께 확장 코드가 호출되지 않는다는 것입니다 – jimmyjambles