다음을 통해 공유


특정 비동기 포스트백에 우선 순위 설정

업데이트: 2007년 11월

기본적으로 페이지에서 여러 비동기 포스트백을 동시에 만드는 경우 가장 최근에 만든 포스트백의 우선 순위가 높습니다. 일부 시나리오에서는 특정 비동기 포스트백에 우선 순위를 설정하고 다른 포스트백을 취소할 수 있습니다.

이 자습서에서는 우선 순위가 높은 포스트백을 제어합니다. 이렇게 하려면 PageRequestManager 클래스의 initializeRequest 이벤트에 대한 이벤트 처리기를 만듭니다. PageRequestManager 클래스에서 발생하는 이벤트 시퀀스에 대한 자세한 내용은 PageRequestManager 이벤트 작업을 참조하십시오.

사전 요구 사항

고유한 개발 환경에서 절차를 구현하려면 다음이 필요합니다.

  • Microsoft Visual Studio 2005 또는 Microsoft Visual Web Developer Express Edition

  • AJAX 사용 ASP.NET 웹 사이트

특정 포스트백 요소에 우선 순위를 설정하는 스크립트 만들기

먼저 브라우저에서 비동기 포스트백을 관리하는 ECMAScript(JavaScript) 코드를 만듭니다.

특정 포스트백 요소에 우선 순위를 설정하는 스크립트를 만들려면

  1. ASP.NET 웹 사이트에서 JScript 파일을 추가하고 이름을 PostbackPrecedence.js로 지정합니다.

  2. 이 파일에 다음 스크립트를 추가합니다.

    Sys.Application.add_load(ApplicationLoadHandler)
    function ApplicationLoadHandler(sender, args)
    {
        if (!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack())
        {
          Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequest);
        }
    }
    
    var divElem = 'AlertDiv';
    var messageElem = 'AlertMessage';
    var exclusivePostBackElement = 'Button1';
    var lastPostBackElement;
    function InitializeRequest(sender, args)
    { 
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        if (prm.get_isInAsyncPostBack() && 
            args.get_postBackElement().id === exclusivePostBackElement) 
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
              args.set_cancel(true);
              ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
              setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }
            else if (lastPostBackElement !== exclusivePostBackElement)
            {
              prm.abortPostBack();
            }
        }
        else if (prm.get_isInAsyncPostBack() && 
                 args.get_postBackElement().id !== exclusivePostBackElement)
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
                args.set_cancel(true);
                ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
                setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }       
        }
        lastPostBackElement = args.get_postBackElement().id;      
    }
    
    function ActivateAlertDiv(visString, msg)
    {
         var adiv = $get(divElem);
         var aspan = $get(messageElem);
         adiv.style.visibility = visString;
         aspan.innerHTML = msg;
    }
    if(typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
    
    Sys.Application.add_load(ApplicationLoadHandler)
    function ApplicationLoadHandler(sender, args)
    {
        if (!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack())
        {
          Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequest);
        }
    }
    
    var divElem = 'AlertDiv';
    var messageElem = 'AlertMessage';
    var exclusivePostBackElement = 'Button1';
    var lastPostBackElement;
    function InitializeRequest(sender, args)
    { 
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        if (prm.get_isInAsyncPostBack() && 
            args.get_postBackElement().id === exclusivePostBackElement) 
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
              args.set_cancel(true);
              ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
              setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }
            else if (lastPostBackElement !== exclusivePostBackElement)
            {
              prm.abortPostBack();
            }
        }
        else if (prm.get_isInAsyncPostBack() && 
                 args.get_postBackElement().id !== exclusivePostBackElement)
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
                args.set_cancel(true);
                ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
                setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }       
        }
        lastPostBackElement = args.get_postBackElement().id;      
    }
    
    function ActivateAlertDiv(visString, msg)
    {
         var adiv = $get(divElem);
         var aspan = $get(messageElem);
         adiv.style.visibility = visString;
         aspan.innerHTML = msg;
    }
    if(typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
    

    이 스크립트는 다음 작업을 수행합니다.

    • Sys.Application 클래스의 load 이벤트에 대한 처리기를 정의합니다. 이 처리기는 PageRequestManager 클래스의 initializeRequest 이벤트에 대해 InitializeRequest라는 처리기를 등록합니다.

    • 비동기 포스트백이 현재 실행 중인지 확인하고 포스트백을 발생시킨 요소의 이름을 확인하도록 InitializeRequest 처리기를 정의합니다. 포스트백을 발생시킨 요소가 단독 포스트백 요소로 지정한 요소(우선 순위가 높아야 하는 요소)인 경우 InitializeRequestEventArgs 클래스의 cancel 속성을 설정하여 새 포스트백을 취소합니다.

    • 메시지를 표시하기 위해 페이지에서 <div> 요소의 표시를 설정/해제하는 ActivateAlertDiv 함수를 정의합니다.

UpdatePanel 컨트롤에서 스크립트 사용

이 절차에서는 페이지에서 만든 스크립트를 사용합니다. 이 페이지에는 두 개의 단추가 있는데 한 단추의 포스트백이 다른 단추의 포스트백보다 우선합니다.

한 포스트백의 포스트백 우선 순위가 높도록 페이지를 만들려면

  1. 새 ASP.NET 웹 페이지 하나를 만들고 디자인 뷰로 전환합니다.

  2. 도구 상자의 AJAX 확장 탭에서 ScriptManager 컨트롤을 두 번 클릭하여 페이지에 추가합니다.

  3. 두 번에 걸쳐 UpdatePanel 컨트롤을 두 번 클릭하여 컨트롤의 인스턴스 두 개를 페이지에 추가합니다.

  4. UpdatePanel 컨트롤에서 도구 상자의 표준 탭을 통해 Label 컨트롤과 Button 컨트롤을 추가합니다.

  5. 두 패널에서 Label 컨트롤의 Text 값을 Panel Initially Rendered로 설정합니다.

  6. Button 컨트롤을 두 번 클릭하여 각 단추의 Click 이벤트에 대한 처리기를 추가합니다.

  7. 인위적으로 지연을 만든 다음 포스트백이 발생한 패널에 현재 시간을 표시하는 다음과 같은 코드를 Click 처리기에 추가합니다.

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        System.Threading.Thread.Sleep(4000)
        Label1.Text = "Last update from server " & DateTime.Now.ToString()
    End Sub
    
    Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
        System.Threading.Thread.Sleep(1000)
        Label2.Text = "Last update from server " & DateTime.Now.ToString()
    End Sub
    
    protected void Button1_Click(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(4000);
        Label1.Text = "Last update from server " + DateTime.Now.ToString();        
    }
    
    protected void Button2_Click(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(1000);
        Label2.Text = "Last update from server " + DateTime.Now.ToString();        
    }
    
    참고:

    Click 이벤트에 대한 처리기는 이 자습서를 위해 지연을 일부러 적용합니다. 실제로는 지연을 적용하지 않습니다. 대신 서버 트래픽이나, 실행 시간이 긴 데이터베이스 쿼리 같이 처리 시간이 오래 걸리는 서버 코드로 인해 시간 지연이 발생합니다.

  8. 소스 뷰로 전환하여 페이지의 <head> 요소에 다음 <style> 블록을 추가합니다.

        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    

    스타일 규칙에서는 UpdatePanel 컨트롤이 렌더링하는 <div> 요소와 포스트백이 취소되는 경우 사용자에게 알려 주는 <div> 요소의 크기를 정의합니다.

  9. 페이지에서 <form> 요소 안에 다음 태그를 추가합니다.

    <div id="AlertDiv" class="MessageStyle">
    <span id="AlertMessage"></span>
    </div>
    
    <div id="AlertDiv" class="MessageStyle">
    <span id="AlertMessage"></span>
    </div>
    

    이 태그에서는 비동기 포스트백이 이미 진행 중이기 때문에 취소되는 경우 메시지를 표시하는 <div> 요소를 정의합니다.

  10. 디자인 뷰로 전환합니다.

  11. 첫 번째 UpdatePanel 컨트롤의 내부를 클릭한 다음 도구 상자의 AJAX 확장 탭을 사용하여 UpdateProgress 컨트롤을 추가합니다.

  12. UpdateProgress 컨트롤 내부를 클릭하고 Panel1 updating …을 입력합니다.

    이렇게 하면 ProgressTemplate 속성이 설정됩니다.

  13. UpdateProgress 컨트롤을 선택하고 속성 창에서 AssociatedUpdatePanelID 속성을 UpdatePanel1로 설정합니다.

    디자이너에서 페이지는 다음 그림과 비슷합니다.

  14. 두 번째 UpdatePanel 컨트롤 내부를 클릭하고 두 번째 UpdateProgress 컨트롤을 추가합니다.

  15. UpdateProgress 컨트롤 내부를 클릭하고 Panel2 updating …을 입력합니다.

    이렇게 하면 ProgressTemplate 속성이 설정됩니다.

  16. UpdateProgress 컨트롤을 선택하고 속성 창에서 AssociatedUpdatePanelID 속성을 UpdatePanel2로 설정합니다.

    디자이너에서 페이지는 다음 그림과 비슷합니다.

  17. ScriptManager 컨트롤을 선택합니다.

  18. 속성 창에서 스크립트 속성을 선택하고 줄임표(…) 단추를 클릭하여 ScriptReference 컬렉션 편집기 대화 상자를 표시합니다.

  19. 추가를 클릭하여 스크립트 참조를 추가합니다.

  20. 스크립트 참조의 경로 속성을 이전에 만든 JavaScript 파일인 PostbackPrecedence.js로 설정합니다.

    ScriptManagerScripts 컬렉션을 사용하여 스크립트 참조를 추가하면 Microsoft AJAX 라이브러리가 로드된 후에 스크립트가 로드됩니다.

  21. 확인을 클릭하여 ScriptReference 컬렉션 편집기 대화 상자를 닫습니다.

  22. 변경 내용을 저장한 다음 Ctrl+F5를 눌러 브라우저에서 페이지를 봅니다.

  23. 첫 번째 패널의 단추를 클릭한 다음 두 번째 패널의 단추를 클릭합니다.

    새 포스트백이 취소되었다는 메시지가 표시됩니다. 첫 번째 패널의 단추는 새 포스트백이 시작되기 전에 완료되어야 합니다. 스크립트 파일에서는 이 동작을 적용하는 논리를 제공합니다.

  24. 두 번째 패널의 단추를 클릭한 다음 첫 번째 패널의 단추를 클릭합니다.

    스크립트 파일에서 그렇게 코딩되지 않았기 때문에 두 번째 패널에 있는 단추의 우선 순위가 높지 않습니다. 따라서 경고 메시지가 표시되지 않고 첫 번째 패널의 단추를 클릭할 때 새 포스트백이 시작됩니다. 이와 같이 가장 최근의 포스트백 우선 순위가 높은 것이 비동기 포스트백의 기본 동작입니다.

    <%@ Page Language="VB" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
        Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
            System.Threading.Thread.Sleep(4000)
            Label1.Text = "Last update from server " & DateTime.Now.ToString()
        End Sub
    
        Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
            System.Threading.Thread.Sleep(1000)
            Label2.Text = "Last update from server " & DateTime.Now.ToString()
        End Sub
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" >
        <title>Postback Precedence Example</title>
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                <Scripts>
                <asp:ScriptReference Path="PostBackPrecedence.js" />
                </Scripts>
                </asp:ScriptManager>
                <asp:UpdatePanel  ID="UpdatePanel1" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 1</strong><br />
    
                    This postback takes precedence.<br />
                    <asp:Label ID="Label1" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button1"  Text="Button" OnClick="Button1_Click" />&nbsp;
                    <asp:UpdateProgress ID="UpdateProgress1"  AssociatedUpdatePanelID="UpdatePanel1">
                    <ProgressTemplate>
                    Panel1 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
                <asp:UpdatePanel  ID="UpdatePanel2" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 2</strong><br />
                    <asp:Label ID="Label2" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button2"  Text="Button" OnClick="Button2_Click" />
                    <asp:UpdateProgress ID="UpdateProgress2"  AssociatedUpdatePanelID="UpdatePanel2">
                    <ProgressTemplate>
                    Panel2 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
               <div id="AlertDiv" class="MessageStyle">
               <span id="AlertMessage"></span>
               </div>
            </div>
        </form>
    </body>
    </html>
    
    <%@ Page Language="C#" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
        protected void Button1_Click(object sender, EventArgs e)
        {
            System.Threading.Thread.Sleep(4000);
            Label1.Text = "Last update from server " + DateTime.Now.ToString();        
        }
    
        protected void Button2_Click(object sender, EventArgs e)
        {
            System.Threading.Thread.Sleep(1000);
            Label2.Text = "Last update from server " + DateTime.Now.ToString();        
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" >
        <title>Postback Precedence Example</title>
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                <Scripts>
                <asp:ScriptReference Path="PostBackPrecedence.js" />
                </Scripts>
                </asp:ScriptManager>
                <asp:UpdatePanel  ID="UpdatePanel1" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 1</strong><br />
    
                    This postback takes precedence.<br />
                    <asp:Label ID="Label1" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button1"  Text="Button" OnClick="Button1_Click" />&nbsp;
                    <asp:UpdateProgress ID="UpdateProgress1"  AssociatedUpdatePanelID="UpdatePanel1">
                    <ProgressTemplate>
                    Panel1 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
                <asp:UpdatePanel  ID="UpdatePanel2" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 2</strong><br />
                    <asp:Label ID="Label2" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button2"  Text="Button" OnClick="Button2_Click" />
                    <asp:UpdateProgress ID="UpdateProgress2"  AssociatedUpdatePanelID="UpdatePanel2">
                    <ProgressTemplate>
                    Panel2 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
               <div id="AlertDiv" class="MessageStyle">
               <span id="AlertMessage"></span>
               </div>
            </div>
        </form>
    </body>
    </html>
    

검토

이 자습서에서는 특정 비동기 포스트백의 우선 순위가 높도록 설정하는 방법, 즉 다른 비동기 포스트백이 시작되기 전에 처리가 완료되도록 설정하는 방법을 설명했습니다. 이러한 동작을 적용하는 논리는 페이지의 스크립트 참조로 추가되는 JavaScript 파일에 있습니다. 새 비동기 포스트백이 시작되기 전에 모든 현재 비동기 포스트백이 완료되도록 이 스크립트 파일을 사용자 지정할 수 있습니다. 그러나 우선 순위를 설정할 포스트백을 지정할 때는 디자인을 신중하게 고려해야 합니다.

참고 항목

개념

PageRequestManager 이벤트 작업

참조

Sys.WebForms.PageRequestManager 클래스

initializeRequest