일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 서진호
- 소년포비소프트
- 훈스닷넷
- 윈도우 모바일
- 실버라이트 코리아
- 거제도
- 루나네스
- UX베이커리
- windows mobile 6.5
- 지승욱
- 윈도데브
- 김춘배
- 황광진
- 옴니아2
- 소년포비
- 신동혁
- winmodev
- 마이크로소프트
- 주신영
- MIX10
- 쉐어포인트코리아
- 헤이맨
- 윈도우모바일
- 윈모데브
- 안드로이드
- 신석현
- 윈도우폰7
- 스마트폰
- 데브피아
- 윈도우폰
- Today
- Total
소년포비의 세계정복!!
비 동기 웹 서비스 호출(Asynchronous WebService) 본문
『 비 동기 웹 서비스 호출』
.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] public string HelloWorld(string name) { //고의로 약 2초 정도 지연시간을 준다 System.Threading.Thread.Sleep(2000);
return "Hello " + name; } |
이렇게 웹 메서드가 만들어 지고 난 후 클라이언트 프로그램을 만들어 웹 참조(Web References)를 하도록 한다.
웹 서비스를 참조 하면 아래 그림처럼 클라이언트의 웹 참조 항목아래에 보면 References.cs 라는
클래스가 있다 (References.cs 파일은 ‘모든 파일 표시’를 해야 나타난다)
이 파일은 웹 서비스를 원격 호출 가능케 하는 Proxy 클래스인데,
파일을 열어 보면 우리가 작성한 웹 메서드인 HelloWorld 에 관련된 메서드가 총 3개 있음을 알 수 있다.
/// <remarks/> [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public string HelloWorld(string name) { object[] results = this.Invoke("HelloWorld", new object[] {name}); return ((string)(results[0])); }
/// <remarks/> public System.IAsyncResult BeginHelloWorld(string name, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("HelloWorld", new object[] {name}, callback, asyncState); }
/// <remarks/> public string EndHelloWorld(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((string)(results[0])); } |
우리가 작성한 HelloWorld 이외에도 BeginHelloWorld, EndHelloWorld 메서드가 자동으로 추가되어 있다.
이 두 메서드가 바로 1.x 에서 비 동기 웹 서비스 호출을 위해 자동으로 생성되는 메서드 인 것이다.
클라이언트에서 비 동기로 웹 서비스를 호출하는 코드를 보자
//웹 서비스 객체 private localhost.Service1 proxy;
//비동기로 HelloWorld 호출 private void button1_Click(object sender, System.EventArgs e) { this.proxy = new localhost.Service1(); proxy.BeginHelloWorld("MKEX",new System.AsyncCallback(CallbackMethod),null); }
public void 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 의 코드를 살펴 보자.
/// <remarks/> public event HelloWorldCompletedEventHandler HelloWorldCompleted;
/// <remarks/> [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public string HelloWorld(string name) { object[] results = this.Invoke("HelloWorld", new object[] {name}); return ((string)(results[0])); }
/// <remarks/> public void HelloWorldAsync(string name) { this.HelloWorldAsync(name, null); }
/// <remarks/> public void HelloWorldAsync(string name, object userState) { if ((this.HelloWorldOperationCompleted == null)) { this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted); } this.InvokeAsync("HelloWorld", new object[] { name}, this.HelloWorldOperationCompleted, userState); }
private void OnHelloWorldOperationCompleted(object arg) { if ((this.HelloWorldCompleted != null)) { System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); this.HelloWorldCompleted(this, new HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); } } |
1.x 의 Reference.cs 와 확연히 달라진 코드임을 알 수 있다.
즉 1.x 에서의 BeginXXX, EndXXX 와 같은 메서드는 없어지고 대신 비 동기 완료를 통지 받기 위한 이벤트(HelloWorldCompletedEventHandler)와
비 동기 웹 메서드 코드(HelloWorldAsync), 이벤트 호출 코드(OnHelloWorldOperationComplete) 자동으로 생성된 것을 볼 수 있다.
클라이언트에서 비 동기로 웹 서비스를 호출하는 코드를 보자
private void 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"); }
//비동기 웹 서비스 호출 완료시 수행되는 이벤트 메서드 public void 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");
여기에 주의사항이 있다.
“이벤트는 한번만 등록되어야 한다”
만일 윈폼 응용프로그램과 같이 웹 서비스 프록시 객체를 미리 생성하고 난 뒤 그 객체를 계속적으로 사용할 경우
위 처럼 웹 메서드를 호출할 때 마다 완료 이벤트를 등록하면 중복 등록되게 되는 것이다.
따라서 이런 경우라면, 반드시 프록시 객체의 생성하는 곳에서 각 웹 메서드에 해당하는 완료 이벤트를 미리 등록하고 난 뒤
실제 웹 메서드 호출할때는 별도로 등록하지 않도록 해야 한다.
'프로그램 세상 > C#' 카테고리의 다른 글
윈폼or모듈단위에서 특정 웹페이지 호출하기 (0) | 2009.10.06 |
---|---|
바인딩 가능한 객체 만들기 (0) | 2009.10.06 |
[스크랩] LINQ 로 LIST 제네릭과 DICTIONARY 로 차집합 구해보기 (0) | 2009.10.05 |
윈폼에서 선그리기 (0) | 2009.10.05 |
[C#]Listview 변경 추가, 삭제, 수정 및 사이즈 변경 (0) | 2009.10.02 |