ASH84

Software Engineer/Developer, co-founder of Payhere. Ex-Banksalad. Intereseted in iteroperability, bootstrap company, writting.

[펌] 웹서비스 비동기 호출

created:2008-05-21
updated:2015-07-03
edit
웹 서비스의 비동기 호출 방법에 대해 정리한 글입니다 닷넷 1.x 기반의 비동기 웹 서비스 호출 방법을 알아 본 뒤 2.0 의 이벤트 기반 비동기 호출에 대해 알아 봅니다 아래의 글을 참고해 주세요 ——————————————————————————————————— **『 비 동기 웹 서비스 호출』** ** ** .NET Framework 는 파일에 대한 I/O 및 네트워크 통신 등에 비 동기 호출 메커니즘을 지원해 왔다. 또한 ADO.NET 2.0 에서는 데이터베이스 관련 작업에도 비 동기 호출을 지원하기 시작했다. 물론 ASP.NET XML WebService 에서도 비 동기 호출을 지원한다. 이번 글에서는 웹 서비스에서의 비 동기 호출 방법에 대해 알아보도록 한다   우선 알아두어야 할 것이 비 동기 웹 서비스 호출이 .NET Framework 1.x 2.0 의 차이점이 있다는 것이다. .NET Framework 2.0에서는 기존의 1.x 에서의 비 동기 호출 보다 직관적이고 이벤트 지향적으로 변경되었다.   **1. .NET Framework 1.x ****에서의 웹 서비스 비 동기 호출** ****  우선 예전 방식(1.x) 에서의 비 동기 호출 방법에 대해 알아보자. 아래와 같이 간단한 웹 서비스의 HelloWorld 웹 메서드를 만들어 보자.  
[WebMethod] publicstring HelloWorld(string name) {       //고의로 약 2초 정도 지연시간을 준다 System.Threading.Thread.Sleep(2000);   return “Hello ” + name; }

이렇게 웹 메서드가 만들어 지고 난 후 클라이언트 프로그램을 만들어 웹 참조(Web References)를 하도록 한다.

웹 서비스를 참조 하면 아래 그림처럼 클라이언트의 웹 참조 항목아래에 보면 References.cs라는

클래스가 있다 (References.cs 파일은 모든 파일 표시를 해야 나타난다)

 

이 파일은 웹 서비스를 원격 호출 가능케 하는 Proxy 클래스인데,

파일을 열어 보면 우리가 작성한 웹 메서드인 HelloWorld 에 관련된 메서드가 총 3개 있음을 알 수 있다.

 

/// [System.Web.Services.Protocols.SoapDocumentMethodAttribute(“http://tempuri.org/Hello World”, RequestNamespace=”http://tempuri.org/”, ResponseNamespace=”http://tempuri.org/ “, Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] publicstring**HelloWorld**(string name) {     object[] results = this.Invoke(“HelloWorld”, newobject[] {name});     return ((string)(results[0])); }         /// public System.IAsyncResult **BeginHelloWorld**(string name, System.AsyncCallback callback , object asyncState) {     returnthis.BeginInvoke(“HelloWorld”, newobject[] {name}, callback, asyncState); }         /// publicstring**EndHelloWorld**(System.IAsyncResult asyncResult) {     object[] results = this.EndInvoke(asyncResult);     return ((string)(results[0])); }
  우리가 작성한 HelloWorld 이외에도 **BeginHelloWorld**, **EndHelloWorld**메서드가 자동으로 추가되어 있다. 이 두 메서드가 바로 1.x 에서 비 동기 웹 서비스 호출을 위해 자동으로 생성되는 메서드 인 것이다.   클라이언트에서 비 동기로 웹 서비스를 호출하는 코드를 보자  
//웹 서비스 객체 private localhost.Service1 proxy;   //비동기로 HelloWorld 호출 privatevoid button1_Click(object sender, System.EventArgs e) {         this.proxy = new localhost.Service1();         proxy.**BeginHelloWorld**(“MKEX”,new System.AsyncCallback(CallbackMethod),null); }   publicvoid CallbackMethod(IAsyncResult ar) {               string result = proxy.**EndHelloWorld**(ar);         MessageBox.Show(result); }
  HelloWorld 웹 메서드를 비 동기로 호출하기 위해서는 **BeginHelloWorld**을 호출해야 한다. 이때 매개변수를 전달하고 비 동기 작업 완료 시 호출 될 Callback 메서드를 지정한다. Callback 메서드에서는 다시 **EndHelloWorld**를 호출하여 비 동기 작업 상태 및 참조 매개변수를 넘겨준다(있을 경우)   이 샘플 프로젝트를 수행해 보면 웹 메서드를 호출하고 난 뒤 기다리는 시간 동안 블로킹이 되지 않고 다른 작업을 수행할 수 있음을 알 수 있다. 즉 비 동기로 웹 서비스가 호출되는 것이다         **2. .NET Framework 2.0 ****에서의 웹 서비스 비 동기 호출** ****  이제 2.0에서의 비 동기 웹 서비스 호출 방법에 대해 알아보자. 위의 샘플과 동일한 웹 서비스를 만들고 클라이언트에 웹 참조를 한 뒤 **Reference.cs**의 코드를 살펴 보자.  
/// publiceventHelloWorldCompletedEventHandler**HelloWorldCompleted**;         ///  [System.Web.Services.Protocols.SoapDocumentMethodAttribute(http://tempuri.org/HelloWo rld”, RequestNamespace=http://tempuri.org/”, ResponseNamespace=http://tempuri.org/”, Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] publicstring**HelloWorld**(string name) {     object[] results = this.Invoke(“HelloWorld”, newobject[] {name});     return ((string)(results[0])); }         /// publicvoid**HelloWorldAsync**(string name) {     this.HelloWorldAsync(name, null); }         /// publicvoid**HelloWorldAsync**(string name, object userState) {     if ((this.HelloWorldOperationCompleted == null)) {         this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);     }     this.InvokeAsync(“HelloWorld”, newobject[] {                 name}, this.HelloWorldOperationCompleted, userState); }         privatevoid**OnHelloWorldOperationCompleted**(object arg) {     if ((this.HelloWorldCompleted != null)) {         System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));         this.HelloWorldCompleted(this, newHelloWorldCompletedEventArgs(invokeArgs. Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));     } }
  1.x Reference.cs 와 확연히 달라진 코드임을 알 수 있다. 1.x 에서의 BeginXXX, EndXXX 와 같은 메서드는 없어지고 대신 비 동기 완료를 통지 받기 위한 이벤트(**HelloWorldCompletedEventHandler**)비 동기 웹 메서드코드(**HelloWorldAsync**), 이벤트 호출 코드(**OnHelloWorldOperationComplete**)자동으로 생성된 것을 볼 수 있다.   클라이언트에서 비 동기로 웹 서비스를 호출하는 코드를 보자  
privatevoid button3_Click(object sender, EventArgs e) {     //웹 서비스 객체     localhost.Service1 proxy = new WindowsApplication4.localhost.Service1();     //비동기 완료시 통지받을 이벤트 핸들러 등록     proxy.HelloWorldCompleted += new WindowsApplication4.localhost.HelloWorldCompletedEventHandler (proxy_HelloWorldCompleted);       //비동기로 HelloWorld 호출      proxy.HelloWorldAsync(“MKEX”); }   //비동기 웹 서비스 호출 완료시 수행되는 이벤트 메서드 publicvoid proxy_HelloWorldCompleted(object sender,localhost. HelloWorldCompletedEventArgs e) {     MessageBox.Show(e.Result); }

1.x 와는 달리 보다 직관적이고 이벤트 지향적으로 변경되었음을 알 수 있다.

비 동기 작업 완료시 통지받을 이벤트를 등록하고,비동기 웹 메서드를 호출하기 위해
XXXAsync
메서드를 호출한다.
이 이벤트 핸들러 메서드에서는 전달된
매개변수(HelloWorldCompletedEventArgs)를 통해 웹 메서드의 반환값을 가져올 수
있게
되는 것이다.

 

 

※ 주의사항

 

앞서 샘플 코드에서는 비 동기 작업 완료 통지를 받기 위한 이벤트를 웹 메서드 호출할 때
등록했었는데,

아래처럼..

 

//비동기 완료시 통지받을 이벤트 핸들러 등록

proxy.HelloWorldCompleted += new WindowsApplication4.localhost.HelloWorldCompletedEventHandler(proxy_HelloWorldCompleted);

//비동기로 HelloWorld 호출

proxy.HelloWorldAsync(“MKEX”);

 

 

여기에 주의사항이 있다.

 

이벤트는 한번만 등록되어야 한다****

 

만일 윈폼 응용프로그램과 같이 웹 서비스 프록시 객체를 미리 생성하고 난 뒤 그 객체를
계속적으로 사용할 경우

위 처럼 웹 메서드를 호출할 때 마다 완료 이벤트를 등록하면 중복 등록되게 되는 것이다.

 

따라서 이런 경우라면, 반드시 프록시 객체의 생성하는 곳에서 각 웹 메서드에 해당하는
완료 이벤트를 미리 등록하고 난 뒤
실제 웹 메서드 호출할때는 별도로 등록하지 않도록
해야 한다.

 

출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=18&MAEULNO=8&no=1286

[![](http://photo-book.hanmail.net/images/book/large/911/l9788956740911.jpg)](http://book.daum.net/bookdetail/book.do?bookid=KOR9788956740911) [NET.XML 웹서비스 STEP BY STEP](http://book.daum.net/bookdetail/book.do?bookid=KOR9788956740911) [상세보기](http://book.daum.net/bookdetail/book.do?bookid=KOR9788956740911)
아담 프리맨 외 지음 | 정보문화사 펴냄
개발자 군에서도 초급, 중급 수준에서 xml 웹 서비스를 빠르고 쉽게 개발하는 과정을 단계별 학습 방식으로 접근하고 있다. 비즈니스에서 바로 이용할 수 있는 신용카드 번화 검증 서비스를 선정한 후, 기본 기능을 구현하는 과정부터 시작하여 고급 기능을 점차적으로 추가해 나가면서 xml 웹 서비스 개발 코드의 완성도를 높여가는 구조로 짜여 있다. 이 책은 채택한 시나리오의 일관성을 유지하면서 실제 어플리케이션 개발에

#dev