문제

바쁜 방법 +c#에 대한 시간 초과를 설정하는 방법.

도움이 되었습니까?

해결책

좋아, 여기 진짜 답변이있다.

...

void LongRunningMethod(object monitorSync)
{
   //do stuff    
   lock (monitorSync) {
     Monitor.Pulse(monitorSync);
   }
}

void ImpatientMethod() {
  Action<object> longMethod = LongRunningMethod;
  object monitorSync = new object();
  bool timedOut;
  lock (monitorSync) {
    longMethod.BeginInvoke(monitorSync, null, null);
    timedOut = !Monitor.Wait(monitorSync, TimeSpan.FromSeconds(30)); // waiting 30 secs
  }
  if (timedOut) {
    // it timed out.
  }
}

   ...

이것은 C#을 사용하는 가장 재미있는 부분 중 두 부분을 결합합니다. 먼저, 메소드를 비동기로 호출하려면 멋진 바지가있는 대의원을 사용하십시오. BeginInvoke 마법.

그런 다음 모니터를 사용하여 메시지를 보냅니다. LongRunningMethod 다시 ImpatientMethod 완료된시기 또는 일정 시간 안에 들어 보지 못한 경우 알리려면 포기하십시오.

(PS- 이것이 진짜 답변이라는 것에 대해 농담입니다. 나는 고양이를 피부에 2^9303 방법이 있다는 것을 알고 있습니다. 특히 .NET에서)

다른 팁

메소드를 변경하지 않는 한 그렇게 할 수 없습니다.

두 가지 방법이 있습니다.

  1. 이 방법은 실행중인 시간을 측정하는 방식으로 내장 된 다음 임계 값을 초과하면 조기에 반환됩니다.
  2. 이 방법은 "이 변수가 설정되면 종료하십시오"라는 변수/이벤트를 모니터링하는 방식으로 내장 된 다음 다른 스레드가 첫 번째 메소드에서 소비 된 시간을 측정 한 다음 해당 변수를 설정할 때 해당 변수를 설정합니다. 시간 경과가 약간의 임계 값을 초과했습니다.

가장 분명하지만 불행히도 잘못된 대답은 "스레드에서 메소드를 실행하고 너무 오래 실행 된 경우 스레드를 사용하십시오"입니다.

유일한 올바른 방법은 방법이 너무 오래 실행될 때 깨끗한 출구를 수행하는 방식으로 협력하는 것입니다.

별도의 스레드에서 메소드를 실행하는 세 번째 방법이 있지만, 끝이 끝날 때까지 기다린 후에는 너무 오래 걸리면 단순히 "나는 그것이 끝날 때까지 기다리지 않을 것입니다. 그것을 버리고 ". 이 경우, 메소드는 여전히 실행되고 결국 완료되지만, 기다리고있는 다른 스레드는 단순히 포기할 것입니다.

세 번째 방법을 누군가에게 전화하여 그들에게 그 책을 빌려주기 위해 집을 검색하도록 요청하고, 5 분 동안 전화 끝을 기다린 후에는 단순히 "aw, chuck it"라고 말하고 전화를 끊습니다. 결국 다른 사람은 책을 찾아서 전화로 돌아가서 더 이상 결과를 돌보지 않는다는 것을 알게됩니다.

하는 동안 Mojofilter의 대답 "긴 메드"가 얼면 누출이 발생할 수 있습니다. 더 이상 결과에 관심이 없다면 작업을 중단해야합니다.

public void LongMethod()
{
    //do stuff
}

public void ImpatientMethod()
{
    Action longMethod = LongMethod; //use Func if you need a return value

    ManualResetEvent mre = new ManualResetEvent(false);

    Thread actionThread = new Thread(new ThreadStart(() =>
    {
        var iar = longMethod.BeginInvoke(null, null);
        longMethod.EndInvoke(iar); //always call endinvoke
        mre.Set();
    }));

    actionThread.Start();
    mre.WaitOne(30000); // waiting 30 secs (or less)
    if (actionThread.IsAlive) actionThread.Abort();
}

이것은 오래된 질문이지만 이제 사용할 수없는 더 간단한 솔루션이 있습니다 : 작업!

다음은 샘플 코드입니다.

var task = Task.Run(() => LongRunningMethod());//you can pass parameters to the method as well
if (task.Wait(TimeSpan.FromSeconds(30)))
    return task.Result; //the method returns elegantly
else
    throw new TimeoutException();//the method timed-out

방법을 별도의 스레드에서 실행하고 모니터링하고 너무 오래 작동하면 종료하도록 강제로 나갈 수 있습니다. 좋은 방법은 당신이 그것을 부를 수 있다면, 메소드에 대한 속성을 개발하는 것입니다. 게시물 샤프 따라서 시청 코드는 귀하의 응용 프로그램을 쓰지 않습니다.

다음을 샘플 코드로 썼습니다 (샘플 코드 부분에 유의하십시오. 작동하지만 멀티 스레딩에서 문제가 발생하거나 문제가되는 메소드가 ThreadAbortException을 캡처하는 경우 다음을 중단 할 수 있습니다).

static void ActualMethodWrapper(Action method, Action callBackMethod)
{
    try
    {
        method.Invoke();
    } catch (ThreadAbortException)
    {
        Console.WriteLine("Method aborted early");
    } finally
    {
        callBackMethod.Invoke();
    }
}

static void CallTimedOutMethod(Action method, Action callBackMethod, int milliseconds)
{
    new Thread(new ThreadStart(() =>
    {
        Thread actionThread = new Thread(new ThreadStart(() =>
        {
            ActualMethodWrapper(method, callBackMethod);
        }));

        actionThread.Start();
        Thread.Sleep(milliseconds);
        if (actionThread.IsAlive) actionThread.Abort();
    })).Start();
}

다음 호출과 함께 :

CallTimedOutMethod(() =>
{
    Console.WriteLine("In method");
    Thread.Sleep(2000);
    Console.WriteLine("Method done");
}, () =>
{
    Console.WriteLine("In CallBackMethod");
}, 1000);

내 코드 가독성을 작업해야합니다.

디버거 또는 OS에 앱이 '매달린'것으로 생각하지 않는 한 메소드는 C#에 시간 초과가 없습니다. 그럼에도 불구하고 처리는 여전히 계속되고 응용 프로그램을 죽이지 않는 한 응답이 반환되고 앱이 계속 작동합니다.

데이터베이스에 대한 통화는 타임 아웃을 가질 수 있습니다.

당신은 당신을 만들 수 있습니까? 비동기 방법 "바쁜"방법이 완료되는 동안 다른 일을 계속할 수 있도록?

플랫폼에서 시간 임계 작업을 동기화 해야하는 앱을 정기적으로 작성합니다. Thread.Abort를 피할 수 있다면 보다 http://blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-pecify-timeout.aspx 그리고 http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation Thread.Abort가 적절한시기에 대한 지침의 경우. 내가 구현 한 개념은 다음과 같습니다.

  • 선택적 실행 : 합리적인 성공 가능성이있는 경우에만 실행됩니다 (타임 아웃을 충족 할 수있는 능력 또는 다른 대기열 항목에 비해 성공 결과의 가능성에 따라). 코드를 세그먼트로 나누고 작업 청크 사이의 예상 시간을 거의 알면 추가 처리를 건너 뛰어야하는지 예측할 수 있습니다. 시간 계산을위한 재귀 함수로 객체 빈 작업을 래핑하거나 근로자가 예상 대기 시간을 알 수있는 컨트롤러 클래스를 갖추면 총 시간을 측정 할 수 있습니다.
  • 선택적 고아 : 합리적인 성공 가능성이 존재하는 경우 수익을 기다리십시오. 인덱스 작업은 관리되는 대기열에서 실행됩니다. 타임 아웃 또는 위험을 초과하는 작업이 다른 시간 초과를 유발하고 고아가되고 널 레코드가 대신에 반환됩니다. 더 긴 실행 작업은 비동기 호출로 래핑 할 수 있습니다. Async Call Wrapper 예제를 참조하십시오. http://www.vbusers.com/codecsharp/codeget.asp?threadid=67&postid=1
  • 조건부 선택 : 선택적 실행과 유사하지만 개별 작업 대신 그룹을 기반으로합니다. 많은 작업이 하나의 성공 또는 실패로 인해 추가 처리가 관련이 없도록 상호 연결된 경우, 실행이 시작되기 전에 확인되는 플래그를 작성하고 긴 하위 작업이 시작되기 전에 다시 확인하십시오. 이는 Parallel. 또는 기타 대기 동시 동시성 작업을 사용할 때 특히 유용합니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top