4

나는 뭔가를 이해하지 못한다고 생각합니다. 나는 그것을 생각했다.Task.Yield()새로운 스레드 / 컨텍스트가 작업을 위해 시작되도록 강요하지만이 답을 다시 읽는다.그것은 단순히 메서드를 비동기로 만듭니다. 그것은 여전히 같은 맥락에있을 것입니다.

교착 상태가 발생하지 않고 여러 작업을 병렬로 생성하고 실행하는 올바른 방법은 asp.net 프로세스에서 무엇입니까?

즉, 다음과 같은 방법이 있다고 가정합니다.

async Task createFileFromLongRunningComputation(int input) { 
    //many levels of async code
}

그리고 특정 POST 경로에 도달하면 위의 방법을 동시에 3 번 실행하고 싶습니다.즉시 반환, 세 가지 모두 완료되면 기록하십시오.

나는 내 행동에 이런 것을 넣어야한다고 생각한다.

public IHttpAction Post() {
   Task.WhenAll(
       createFileFromLongRunningComputation(1),
       createFileFromLongRunningComputation(2),
       createFileFromLongRunningComputation(3)
   ).ContinueWith((Task t) =>
      logger.Log("Computation completed")
   ).ConfigureAwait(false);
   return Ok();

}

무엇이 들어가야하는지createFileFromLongRunningComputation? 나는 생각했다.Task.Yield맞았지 만 분명히 그렇지 않다.


  • 부름ConfigureAwait네가 실제로 그렇게하지 않으면 무의미하다.await그만큼Task. - Servy
  • 고마워요. @ 세이비. 나는 그걸 알았지 만 내 마음이 미끄러웠다. - George Mauer

2 답변


6

그만큼옳은동시 작업을 다른 스레드로 오프로드하는 방법은Task.Run로시 피디아가 제안한대로.

에서 백그라운드 처리를위한 최상의 솔루션ASP.Net(귀하의AppDomain모든 작업과 함께 자동으로 재활용 / 종료 될 수 있음)스콧 한젤 만스티븐 클리어 리님의 블로그 (예 : HangFire)

그러나, 당신은할 수 있었다이용하다Task.Yield함께ConfigureAwait(false)같은 것을 달성하기 위해.

모든Task.Yield그렇지 않으면 메소드의 나머지 부분이 동 기적으로 진행되지 않도록 대기하는 것이 반환됩니다 (IsCompleted반환falseOnCompleted~을 실행하다Action매개 변수).ConfigureAwait(false)무시하다SynchronizationContext나머지 메서드는 강제로 실행되도록합니다.ThreadPool실.

두 가지를 함께 사용하면async메서드는 즉시 실행되는 작업을 반환합니다.ThreadPoolTask.Run) :

async Task CreateFileFromLongRunningComputation(int input)
{
    await Task.Yield().ConfigureAwait(false);
    // executed on a ThreadPool thread
}

편집하다: George Mauer는 다음과 같이 지적했다.Task.Yield보고YieldAwaitable너는 사용할 수 없어.ConfigureAwait(false)이 방법은Task수업.

다음과 같이 비슷한 것을 얻을 수 있습니다.Task.Delay매우 짧은 시간 제한으로 동기식이 아니지만 많은 시간을 낭비하지 않아도됩니다.

async Task CreateFileFromLongRunningComputation(int input)
{
    await Task.Delay(1).ConfigureAwait(false);
    // executed on a ThreadPool thread
}

더 나은 옵션은YieldAwaitable단순히SynchronizationContext사용하는 것과 같다.ConfigureAwait(false)않습니다 :

async Task CreateFileFromLongRunningComputation(int input)
{
    await new NoContextYieldAwaitable();
    // executed on a ThreadPool thread
}

public struct NoContextYieldAwaitable
{
    public NoContextYieldAwaiter GetAwaiter() { return new NoContextYieldAwaiter(); }
    public struct NoContextYieldAwaiter : INotifyCompletion
    {
        public bool IsCompleted { get { return false; } }
        public void OnCompleted(Action continuation)
        {
            var scheduler = TaskScheduler.Current;
            if (scheduler == TaskScheduler.Default)
            {
                ThreadPool.QueueUserWorkItem(RunAction, continuation);
            }
            else
            {
                Task.Factory.StartNew(continuation, CancellationToken.None, TaskCreationOptions.PreferFairness, scheduler);
            }
        }

        public void GetResult() { }
        private static void RunAction(object state) { ((Action)state)(); }
    }
}

이것은 권장 사항이 아니라 Task.Yield 질문에 대한 답변입니다.


  • 이 질문에 대한 정답입니다.실제 질문. 나의 대답은 OPs 접근법이 좋은 것인지에 대한 더 많은 논의 포인트를 가지고있다. - rossipedia
  • 실제로 @rossipedia. 다시 말씀 드리지만 실제 코드가 어떻게 표시되는지는 아닙니다. - i3arnon
  • Oy vey, 이제 4.5.2를 배포하도록 인프라에 확신시킬 수 있는지 알아봐야합니다. - George Mauer
  • Task.Yield()작업을 반환하지 않으므로 아무 작업도 수행되지 않습니다.ConfigureAwait기능. 그래서 권장되지 않는 접근 방식은 효과가 없습니다. - George Mauer
  • @GeorgeMauer 당신 말이 맞아요. 나는 생각하지 않아. 정말 흥미로운 해결책을 추가했습니다. - i3arnon

4

(라르 논의 대답올바른 것입니다. 이 답변은 OP가 제기 한 접근 방식이 좋은 것인지에 대한 논의가 더 많습니다.)

정말로 특별한 것은 필요 없습니다. 그만큼createFileFromLongRunningComputation메서드는 특별한 것이 필요하지 않습니다.await일부 비동기 메소드를 호출하고ConfigureAwait(false) 할까요교착 상태를 피하십시오. 평범한 것에서 아무것도하지 않는다고 가정하십시오 (아마도 메서드 이름이 주어지면 단지 파일 I / O 일 것입니다).

경고:

이것은 위험합니다. 작업이 너무 오래 끝내면 ASP.net은이 상황에서 당신 밑에서 깔개를 꺼낼 가능성이 큽니다.

의견 제시 자 중 한 명이 지적했듯이이를 달성하는 더 좋은 방법이 있습니다. 그들 중 하나는HostingEnvironment.QueueBackgroundWorkItem(.NET 4.5.2 이상에서만 사용 가능).

장기 실행 계산이 완료하는 데 오랜 시간이 걸리는 경우 ASP.net에서 완전히 제외하는 것이 좋습니다. 이러한 상황에서 더 좋은 방법은 일종의 메시지 큐와 IIS / ASP.net 외부에서 이러한 메시지를 처리하는 서비스를 사용하는 것입니다.


  • @GeorgeMauer 그런데 제목이 '여러 작업을 기다리고 있습니다'라는 이유는 무엇입니까? 또한 이것은 매우 위험합니다. asp.net에서 백그라운드 처리를 원한다면 더 좋은 방법이 있습니다. - i3arnon
  • @ GeorgeMauer 필요한 것은 다음과 같습니다.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx - i3arnon
  • 또한 관련 -blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html - Daniel Kelley
  • @GeorgeMauer : ASP.NET에서이 일을해서는 안됩니다. 독립적 인 백엔드 작업자 프로세스가있는 지속적인 대기열이 있어야합니다. - Stephen Cleary
  • 그는 이미 비동기 작업을 수행하고 있습니다. 거기에 전화를 걸지 않아도됩니다.Run; 스레드 풀에서 작업을 예약하는 데 시간 낭비가 있습니다.스타트비동기 조작. - Servy

연결된 질문


관련된 질문

최근 질문