문제

ASP.Net 응용 프로그램에서 사용자는 웹 페이지의 단추를 클릭한 다음 이벤트 처리기를 통해 서버의 개체를 인스턴스화하고 개체에 대한 메서드를 호출합니다.이 방법은 작업을 수행하기 위해 외부 시스템으로 이동하며 시간이 걸릴 수 있습니다.그래서 제가 하고 싶은 것은 다른 스레드에서 해당 메소드 호출을 실행하여 "귀하의 요청이 제출되었습니다"라는 메시지와 함께 사용자에게 제어권을 반환할 수 있는 것입니다.사용자가 개체의 상태를 계속 폴링할 수 있다면 더 좋을 것 같지만 실행 후 잊어버리는 방식으로 이 작업을 수행하는 것은 상당히 기쁩니다.

내가 모르는 것은 사용자 세션이 만료되더라도 IIS가 내 스레드가 계속 실행되도록 허용하는지 여부입니다.사용자가 이벤트를 발생시키고 우리가 서버에서 개체를 인스턴스화하고 새 스레드에서 메서드를 실행한다고 상상해 보세요.사용자는 "귀하의 요청이 제출되었습니다"라는 메시지에 만족하고 브라우저를 닫습니다.결국 이 사용자 세션은 IIS에서 시간 초과되지만 스레드는 계속 실행되어 작업을 수행할 수 있습니다.IIS는 스레드가 계속 실행되도록 허용합니까, 아니면 사용자 세션이 만료되면 스레드를 종료하고 개체를 폐기합니까?

편집하다:답변과 의견을 통해 이를 수행하는 가장 좋은 방법은 장기 실행 처리를 IIS 외부로 옮기는 것임을 이해합니다.다른 모든 것 외에도 이것은 appdomain 재활용 문제를 다룹니다.실제로는 제한된 시간 내에 버전 1을 시작해야 하고 기존 프레임워크 내에서 작업해야 하므로 서비스 계층을 피하고 싶기 때문에 IIS 내부에서 스레드를 실행하고 싶습니다.실제로 여기서 "장기 실행"은 몇 분 밖에 걸리지 않으며 웹 사이트의 동시성은 낮으므로 괜찮습니다.그러나 다음 버전에서는 반드시 별도의 서비스 계층으로 분할해야 합니다.

도움이 되었습니까?

해결책

원하는 것을 달성할 수 있지만 일반적으로 이는 나쁜 생각입니다.여러 ASP.NET 블로그 및 CMS 엔진은 공유 호스팅 시스템에 설치 가능하고 설치해야 하는 Windows 서비스에 종속되지 않기를 원하기 때문에 이 접근 방식을 사용합니다.일반적으로 앱이 시작될 때 Global.asax에서 장기 실행 스레드를 시작하고 해당 스레드 프로세스를 대기열에 추가합니다.

요청을 처리하기 위해 IIS/ASP.NET에서 사용할 수 있는 리소스를 줄이는 것 외에도 AppDomain이 재활용될 때 스레드가 종료되는 문제가 있으며, 다음과 같이 작업이 진행 중인 동안 작업의 지속성을 처리해야 합니다. AppDomain이 다시 시작되면 작업 백업을 시작합니다.

많은 경우 AppDomain은 기본 간격으로 자동으로 재활용되고 web.config 등을 업데이트하는 경우에도 재활용됩니다.

언제든지 종료되는 스레드의 지속성 및 트랜잭션 측면을 처리할 수 있다면 일정 간격으로 사이트에 요청을 보내는 외부 프로세스를 가짐으로써 AppDomain 재활용 문제를 해결할 수 있습니다. X분 내에 자동으로 다시 시작되도록 보장됩니다.

다시 말하지만 이는 일반적으로 나쁜 생각입니다.

편집하다:다음은 이 기술이 실제로 사용되는 몇 가지 예입니다.

커뮤니티 서버:Windows 서비스 사용과예정된 간격으로 코드를 실행하는 백그라운드 스레드 웹 사이트가 처음 시작될 때 백그라운드 스레드 만들기

편집(먼 미래에서) - 요즘에는 행파이어.

다른 팁

나는 받아 들여진 대답에 동의하지 않습니다.

배경 스레드 (또는 작업) 사용 Task.Factory.StartNew)는 asp.net에서 괜찮습니다. 모든 호스팅 환경과 마찬가지로 셧다운을 통치하는 시설을 이해하고 협력 할 수 있습니다.

ASP.NET에서는 종료시를 사용하여 우아하게 중지 해야하는 작업을 등록 할 수 있습니다. HostingEnvironment.RegisterObject 방법. 보다 이 기사 토론에 대한 의견.

(Gerard는 그의 의견에서 지적했듯이 지금도 있습니다. HostingEnvironment.QueueBackgroundWorkItem 전화를 걸어 RegisterObject 작업 할 배경 항목에 대한 스케줄러를 등록하려면 전반적으로 새로운 방법은 작업 기반이므로 더 좋습니다.)

당신이 종종 그것이 나쁜 아이디어라는 것을 듣는 일반적인 주제에 관해서는, Windows 서비스를 배포하는 대안 (또는 다른 종류의 추가 프로세스 응용 프로그램)을 고려하십시오.

  • 웹 배포로 더 이상 사소한 배포가 없습니다
  • Azure 웹 사이트에 순전히 배포 할 수 없습니다
  • 배경 작업의 특성에 따라 프로세스가 의사 소통해야 할 것입니다. 즉, 일부 형태의 IPC 또는 서비스가 공통 데이터베이스에 액세스해야합니다.

또한 일부 고급 시나리오는 요청과 동일한 주소 공간에서 배경 스레드가 실행되어야 할 수도 있습니다. ASP.NET이 .NET을 통해 가능해지는 큰 이점으로이를 수행 할 수 있다는 사실을 알 수 있습니다.

이 작업에 IIS 스레드 풀의 스레드를 사용하고 싶지 않을 것입니다. 그렇게 하면 해당 스레드가 향후 요청을 처리할 수 없게 되기 때문입니다.당신은 조사할 수 있습니다 ASP.NET 2.0의 비동기 페이지, 하지만 그것도 정답은 아닐 것입니다.대신에, 당신이 이익을 얻을 것 같은 것은 다음을 살펴보는 것입니다. 마이크로소프트 메시지 큐.기본적으로 대기열에 작업 세부 정보를 추가하면 다른 백그라운드 프로세스(Windows 서비스)가 해당 작업을 수행하게 됩니다.그러나 중요한 점은 백그라운드 프로세스가 IIS와 완전히 분리되어 있다는 것입니다.

사용하는 것이 좋습니다 행파리 그러한 요구 사항에 대해. 그것은 멋진 화재와 엔진이 백그라운드에서 실행되는 것을 잊고, 다양한 아키텍처를 지원하며, 지속 가능성이 있기 때문에 신뢰할 수 있습니다.

여기에는 좋은 스레드와 샘플 코드가 있습니다. http://forums.asp.net/t/1534903.aspx?pageindex=2

나는 앱 풀을 살아있게 유지하기 위해 내 웹 사이트에서 내 웹 사이트에서 Keep Alive 페이지를 호출한다는 아이디어를 가지고 놀았습니다. 응용 프로그램은 언제든지 재활용 할 수 있으므로이 방법을 사용하는 경우 정말 좋은 복구 처리가 필요합니다. 많은 사람들이 언급했듯이 다른 서비스 옵션에 액세스 할 수있는 경우 올바른 접근 방식이 아니지만 공유 호스팅의 경우 유일한 옵션 중 하나 일 수 있습니다.

앱 풀을 살아있는 상태로 유지하려면 스레드가 처리하는 동안 자신의 사이트에 요청할 수 있습니다. 이는 프로세스가 오랫동안 실행되면 앱 풀을 살아 남기는 데 도움이 될 수 있습니다.

string tempStr = GetUrlPageSource("http://www.mysite.com/keepalive.aspx");


    public static string GetUrlPageSource(string url)
    {
        string returnString = "";

        try
        {
            Uri uri = new Uri(url);
            if (uri.Scheme == Uri.UriSchemeHttp)
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
                CookieContainer cookieJar = new CookieContainer();

                req.CookieContainer = cookieJar;

                //set the request timeout to 60 seconds
                req.Timeout = 60000;
                req.UserAgent = "MyAgent";

                //we do not want to request a persistent connection
                req.KeepAlive = false;

                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                Stream stream = resp.GetResponseStream();
                StreamReader sr = new StreamReader(stream);

                returnString = sr.ReadToEnd();

                sr.Close();
                stream.Close();
                resp.Close();
            }
        }
        catch
        {
            returnString = "";
        }

        return returnString;
    }

우리는이 경로를 시작했고 실제로 앱이 하나의 서버에있을 때 괜찮 았습니다. 여러 기계로 확장하려면 (또는 웹 가렌에서 여러 W3WP를 사용하기 위해) 작업 대기열, 오류 처리, 검색 및 올바른 잠금의 까다로운 문제를 다시 평가하고 하나만 보장하는 방법을 살펴 봐야했습니다. 서버는 다음 항목을 선택합니다.

... 우리는 우리가 배경 처리 엔진을 작성하는 사업에 있지 않다는 것을 깨달았으므로 기존 솔루션을 찾고 멋진 OSS 프로젝트를 사용하여 착륙했습니다. 행파리

Sergey Odinokov는 시작하기 쉬운 실제 보석을 만들었으며 작업이 지속되고 대기되는 방식의 백엔드를 교체 할 수 있습니다. Hangfire는 백그라운드 스레드를 사용하지만 작업을 지속시키고 재 훈련을 처리하며 작업 대기열에 대한 가시성을 제공합니다. 따라서 행 파이어 작업은 강력하고 재활용되는 앱 도메인의 모든 미래에서 살아남습니다.

기본 설정은 SQL Server를 스토리지로 사용하지만 확장시기에 Redis 또는 MSMQ를 교체 할 수 있습니다. 또한 모든 작업 및 해당 상태를 시각화하고 작업을 재평가 할 수있는 우수한 UI가 있습니다.

내 요점은 배경 스레드에서 원하는 것을 할 수 있지만 확장 가능하고 강력하게 만드는 많은 작업이 있다는 것입니다. 간단한 워크로드에는 적합하지만 상황이 더 복잡해지면이 노력을 거치지 않고 목적으로 구축 된 라이브러리를 사용하는 것을 선호합니다.

사용 가능한 옵션에 대한 더 많은 관점을 보려면 Scott Hanselman 's를 확인하십시오. 블로그 ASP.NET에서 배경 작업을 처리하기위한 몇 가지 옵션을 다룹니다. (그는 Hangfire를 빛나는 리뷰를 주었다)

또한 John이 언급 한 바와 같이 Phil Haack 's를 읽는 가치 블로그 접근 방식이 문제가되는 이유와 AppDomain이 언로드 될 때 스레드 작업을 우아하게 중지하는 방법에 대해.

그 작업을 수행하기 위해 Windows 서비스를 만들 수 있습니까? 그런 다음 웹 서버에서 .net 리모 팅을 사용하여 Windows 서비스를 호출하여 작업을 수행합니까? 그것이 내가 할 일이라면.

이렇게하면 IIS에 전달해야 할 필요가 없으며 처리 능력의 일부를 제한합니다.

그렇지 않다면 프로세스가 완료되는 동안 사용자가 거기에 앉도록 강요 할 것입니다. 그렇게하면 IIS에 의해 완료되고 죽이지 않도록합니다.

IIS에서 장기 실행 작업을 호스팅하는 지원 방법이 하나있는 것 같습니다. 워크 플로 서비스 특히 함께 설계된 것 같습니다 Windows Server AppFabric. 이 설계는 장기 실행 작업의 자동 지속성 및 재개를 지원하여 응용 프로그램 풀 재활용을 허용합니다.

백그라운드에서 작업을 실행할 수 있으며 요청이 종료 된 후에도 완료됩니다. 끊임없는 예외를 던지지 마십시오. 일반적으로 당신은 항상 당신의 예외를 던지기를 원합니다. 예외가 새 스레드에 던져지면 충돌합니다. IIS 작업자 프로세스 -W3wp.exe, 당신은 더 이상 요청의 컨텍스트에 있지 않기 때문입니다. 또한 사용중인 경우 프로세스 내 메모리 백업 세션 외에 실행중인 다른 배경 작업을 죽일 것입니다. 이것은 진단하기 어려울 것이므로 연습이 낙담 한 이유입니다.

비동기 작업을 실행하기 위해 대리 프로세스 만 작성하십시오. Windows 서비스 일 필요는 없습니다 (대부분의 경우 더 최적의 접근 방식이지만 MSMQ는 죽임을 당합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top