Study/WebService2008. 2. 20. 01:07

Working With Asynchronous .NET Web Service Clients
By Kenn Scribner

by Kenn Scribner of Wintellect

While many developers realize that consuming Web Services using the asynchronous call mechanisms built into .NET is useful, they also find it confusing. If you've had trouble trying to use the asynchronous call methods in your generated proxies—or if you're wondering what asynchronous means in the first place—this article helps clarify some things and makes your programming tasks (at least as related to asynchronous processing) a little easier.

The general discussion focuses on consuming .NET Web Services, but because asynchronous processing is built into .NET, the information is applicable to any asynchronous processing you might want to perform. That is, when you create a proxy for your Web Service, the asynchronous methods are baked in. But, you also have similar asynchronous methods built into your .NET delegate classes and therefore also can utilize delegates in an asynchronous fashion (hmm, perhaps fodder for another article: using .NET delegates as the poor man's multithreaded processing platform?).

Web Service Proxies

To be clear about Web Services and their consumption, Figure 1 presents the basic architecture.



Click here for a larger image.

Figure 1: Generalized Web Service Communication Architecture

The ultimate goal of a Web Service is to give the client the illusion that remote resources and processing capabilities are actually present on the client computer. For this to occur, some software on the client must generate and issue the request (as well as interpret the response), and some software on the server must accept requests, translate them into formats the server can work with, and activate the server-side processing itself. The first of these pieces of software is known as the proxy, because it simulates the server on the client. The proxy communicates with some form of stub, whose job is to take the SOAP-based XML and convert it into binary information resident within the server's memory. The stub also initiates the server-side processing.

When you use .NET to consume Web Services, it can create this proxy for you automatically, either with Visual Studio or the tool that ships with .NET itself, Wsdl.exe. Either tool queries the Web Service for its service description, as described by the Web Service Description Language (WSDL), and then generates the proxy source code for you by interpreting the WSDL it finds.

If you open the proxy source code you've been given, you should find all of the Web-based methods exposed by the Web Service. But, you'll also find some curiously named methods beginning with "Begin" and "End" and ending with the Web methods you'd expect. That is, if the Web Service exposed a single method named "CalcPayment," in your proxy you would find executable code for not only CalcPayment itself, but also for BeginCalcPayment and EndCalcPayment. You will use these "begin" and "end" methods for your asynchronous processing.

Asynchronous Processing

What exactly is asynchronous processing and why should you be concerned about using it? To answer that, let me first ask you a question: How do you feel when an application's user interface locks for some extended period of time while it processes your selected action? Most of us tend to dislike that kind of application behavior—and I'm being kind here.

Instead, we prefer our user interfaces responsive, even when working on actions we know to be lengthy. If that action involved a call to a Web Service, especially one over the Internet (versus simply a local one found on our intranet), the request might take quite a bit of time to process. Delays from 200 milliseconds up to full seconds are not uncommon. For example, say a given Web Service takes on average of 600 milliseconds to complete, but the user waits over half a second for each call. That might not seem like much, but to a user it could prove to be a major annoyance. Remember, the user interface locks entirely for this call duration.

The process thread used to make the call to the Web Service causes the locking phenomenon. The user interface usually locks up because the thread servicing the user interface (button clicks, painting behavior, and so forth) is also the very same thread making an extended call somewhere else, waiting for data. It might be a Web Service call, but it also might be some lengthy local financial calculation, database query, or whatever. Anything that takes a significant amount of time to process, if serviced by the same thread that manages the user interface, will cause the user interface to cease taking inputs from the user and appear to be locked. In general, try to avoid this. Such behavior has been known to cause users to throw keyboards, break monitors, and worst of all, no longer purchase your software.

Getting back to asynchronous processing, my dictionary defines asynchronous as "pertaining to a transmission technique that does not require a common clock between the communicating devices." Overlooking the clock reference, you could rewrite this definition in its loosest terms to read something like "asynchronous processing is a form of multithreaded programming where a primary thread activates a lengthy process to be managed by a secondary thread." The primary thread's task is complete when the process is activated, so it can (almost immediately) return to its main function, which in this case might be managing the user interface. The secondary thread then begins the lengthy process and sustains the wait, a procedure known as blocking. It locks and ceases processing, waiting for the lengthy process to terminate. It then (optionally) reports back to the primary thread the results of the process.

A side benefit of this is that you then can easily make multiple such processing calls in parallel. If the primary thread made multiple calls (synchronously, on the same thread), each synchronous call would need to be made sequentially, thus increasing the processing time greatly.

Asynchronous .NET Web Requests

In the case of a Web Service called using the proxy's asynchronous call methods, the secondary thread is actually a thread from the .NET thread pool. What's great about that is you don't need to create and manage your own thread (or pool of threads, which is even more complicated). Instead, when you call the "begin" method found in your proxy, you pass into that a callback function .NET will use to provide the Web Service response to your application. Always remember that when your callback function is executed, the .NET thread executes it, not the primary thread (which is most likely the thread that created your user interface). I'll revisit this a bit later in this discussion.

Although not the only way to process asynchronous Web Service calls, I finalize the call to the Web Service by extracting the resultant parameter values, as well as the method return value, in the callback function. This finalization is the call to the "end" method found in your Web Service proxy. The "end" method retrieves the resulting parameter objects (out and ref parameters), as well as the return value, and provides them to you for further processing. The beauty is that your primary thread doesn't have to block while waiting for the Web Service to complete. Instead, a .NET thread is used, and your user interface is free to continue to accept user inputs and be just as responsive and snappy as it was prior to the Web Service invocation. Later, when the call is complete, you can marshal the data back to your user interface thread and do whatever is necessary at that point.

You could, if you desire, perform some wait processing in your main thread (a technique for this is described in the MSDN article "Communicating with XML Web Services Asynchronously"). Personally, I find this to be of limited value because you're still employing the primary thread to perform the wait processing. But, I would be remiss if I didn't at least mention it.

Asynchronous Behavior Is a Client-Side Phenomenon

No matter how you call your Web Service, synchronously or asynchronously, each call is the same to the Web Service. You're still sending in one SOAP packet, and you'll still (hopefully) receive a single SOAP packet in response.

Marshaling—a Side Note for Windows User Interface Programmers

Marshaling—what an ugly sounding word. It harkens back to the old COM programming days when we had to deal with passing data between threads. Oh, but that's exactly what we're doing here! Uh-oh. Actually, it's not so bad. Marshaling basically is the process of converting information for communication between threads.

Because Windows is a virtual, memory-based operating system, memory addresses are meaningless between processes. If you pass information between processes based upon that information's memory address, it will have no meaning in the other process and this second process likely will crash. Old COM programmers (and I include myself here) know this all too well.

Fortunately, .NET handles marshaling for you without too much effort on your part. The age-old Windows rule that only—and I mean only—the thread that created a window can update that window's state also helps. Therefore, you can't just change window text, color, shape, size, or political affiliation willy-nilly without making sure you're doing so from the thread that created the window. Forget this fact and Windows becomes unpredictable. Sometimes things work, and sometimes they don't. If you follow the basic rule, though, and always let the window's creating thread update the window, your code (and application) won't crash and burn.

Delegates in .NET

If you look into your MSDN documentation under System.Windows.Forms.Control, you'll find a curious method called Invoke(). The first sentence of the associated documentation page reads: "Executes a delegate on the thread that owns the control's underlying window handle." Wow, that sounds a lot like "the thread that created the window." But what's this "executes a delegate" stuff?

We're back into the guts of .NET, but this time we're looking at the delegate and its relationship to events and event handling. If you create a delegate that has as its parameters the very same parameters that the Web Service returned, .NET will marshal those parameters for you and ship them to the particular window's creation thread. There you have it! The parameters are now available to the window's creating thread, so at that point you can update the window to your heart's content. Easy, right?

The truth is it isn't too bad, once you've seen it in action. In .NET terms, a delegate is essentially a type-safe callback function. So, what you need to do utilize it is:

  1. Design a method in your application that accepts the same parameters the Web Service returned;
  2. Designate it as a delegate data type; and
  3. Create one of these delegates for use with Invoke().

I'll show some code for this shortly. But first, back to asynchronous Web Service calls in general.

출처 : developer.com(http://www.developer.com/net/net/article.php/11087_3408531_1)

Posted by 굥쓰
Study/MSDN2008. 2. 20. 00:33

서버 측 비동기 웹 메소드

Matt Powell
Microsoft Corporation

2002년 10월

요약: Matt Powell은 높은 성능의 Microsoft ASP.NET 웹 서비스를 생성하기 위해 서버 쪽에서 비동기 웹 메소드를 사용하는 방법을 보여줍니다.


소개

9월의 3번째 컬럼 (영문) 에서, Microsoft .NET Framework의 서버쪽 특성을 사용해서 HTTP를 통한 비동기 웹서비스 호출에 관해 썼습니다. 이 방법은 많은 백그라운드 쓰레드나 응용 프로그램에 락을 거는 것 없이도 웹 서비스를 호출하는 매우 유용한 방법입니다. 이제 우리는 서버 쪽에서 비슷한 특성을 제공하는 비동기 웹 메소드에 대해 살펴보고자 합니다. 비동기 웹 메소드는 ISAPI extension에서 사용하는 HSE_STATUS_PENDING로써 제공되는 높은 성능의 방식과 비슷하지만, 쓰레드 풀을 직접 관리하는 부담없이 관리되는 코드 안에서 동작되는 모든 이점을 누릴 수 있습니다.

첫째로 일반적인, 동기적 Microsoft ASP.NET의 웹 메소드를 살펴봅시다. 동기적인 웹 메소드에 대한 응답은 메소드로부터 반환이 되었을 때 전송됩니다. 만일 요청을 완료하기에 상대적으로 긴 시간이 걸린다면, 메소드 호출이 끝났을 때까지 요청을 처리하는 쓰레드를 사용하게 됩니다. 불행히도, 오랜 시간이 걸리는 것은 데이터베이스에 질의를 하는 경우와 같은 작업이거나, 다른 웹 서비스를 호출하는 경우입니다. 예를 들면 만일 데이터베이스 호출을 하는 경우, 현재 쓰레드는 데이터베이스에 대한 호출을 완료할 때까지 기다리게 됩니다. 현재 쓰레드는 질의로부터 응답이 올 때까지 아무것도 하지 못하고 기다리게 됩니다. 비슷한 문제들이 TCP 소켓에 대한 호출을 기다리거나 최후위의 웹 서비스를 완료할 때까지 기다리는 일이 일어납니다.

쓰레드들이 대기 중이라는 것을 좋지 않은 일입니다 - 특별히 스트레스를 받는 서버 시나리오에서는 더욱 그러합니다. 대기중인 쓰레드는 다른 요청들을 서비스하는 것과 같은, 생산적인 어떠한 것도 처리할 수 없기 때문입니다. 우리가 서버에서 오랜 시간이 걸리는 백그라운드 프로세스를 시작할 때 필요한 것, 그러나 ASP.NET 프로세스 풀로 현재 쓰레드를 반환하는 것입니다. 그리고 오랜 시간이 걸리는 백그라운드 프로세스가 종료되었을 때, 우리는 ASP.NET에 대한 요청의 완료 신청을 받고 요청에 대한 처리를 마치도록 호출된 콜백 함수를 가지는 것입니다. 이것은 ASP.NET에서 비동기 웹 메소드를 통해 제공되는 특징입니다.

어떻게 비동기 웹 메소드가 동작하는가

웹 메소드를 사용하는 전형적인 ASP.NET 웹 서비스를 우리가 작성할 때, Microsoft Visual Studio .Net은 단순하게 웹 메소드들에 대한 요청을 받았을 때 호출될 수 있는 어셈블리를 생성하도록 코드를 컴파일해 줍니다. 이 어셈블리는 SOAP에 관한 어떤 것도 알지 못합니다. 당신의 응용 프로그램이 처음 실행 될 때, ASMX 핸들러는 어느 웹 메소드가 노출되었는지를 검사하도록 어셈블리를 나타내야 합니다. 일반적인, 동기적 요청에 대해서 이것은 단순히 연관된 WebMethod 속성을 가진 어던 메소드를 발견하는 문제이고, 그리고 SOAPAction HTTP 헤더에 기초해서 올바른 메소드를 호출하도록 로직을 설정하면 됩니다.

비동기 요청에 대해서는, 비동기 적이라고 알 수 있는 특정한 종류의 시그니처를 가진 웹 메소드를 ASMX 핸들러가 리플렉션(Reflection) 동안 찾게 됩니다. 이 경우, 다음의 규칙을 따르는 한 쌍의 메소드들을 찾게 됩니다:

  • BeginXXXEndXXX의 이름을 가지는 웹 메소드가 있으며 여기서 XXX는 노출하기를 원하는 메소드의 이름을 나타냅니다.
  • BeginXXX 함수는 IAsyncResult 인터페이스를 반환하며 마지막 두 개의 입력 파라메터는 AsyncCallback과 객체를 취합니다.
  • The EndXXX 함수는 IAsyncResult인터페이스형 파라미터를 취합니다.
  • 양쪽 모두 WebMethod 속성으로 표시되어야 합니다.

만일 ASMX 핸들러가 이러한 모든 요구 조건에 맞는 2개의 메소드를 발견했다면, 일반 웹 메소드처럼 WSDL에 XXX메소드를 노출시킵니다. 입력으로써 BeginXXX에 대한 시그니처안에 AsyncCallback 파라미터에 정의된 파라미터들을 받게 되며, EndXXX함수에 의해 반환되는 것을 반환하게 됩니다. 만일 우리가 동기적인 선언형태의 웹 메소드를 가졌다면 이와 같이 보일 겁니다:

    [WebMethod]
    public string LengthyProcedure(int milliseconds) {...}

비동기적인 선언의 경우 아래와 같이 보입니다:

    [WebMethod]
    public IAsyncResult BeginLengthyProcedure(
                            int milliseconds, 
                            AsyncCallback cb, 
                            object s) {...}

    [WebMethod]
    public string EndLengthyProcedure(IAsyncResult call) {...}

각각에 대한 WSDL은 동일합니다.

ASMX핸들러가 어셈블리를 리플렉션하고 비동기적인 웹 메소드를 감지한 후에, 반드시 그 메소드에 대한 요청을 동기적인 요청과는 다르게 처리해야 합니다. 단순하게 메소드를 호출하는 것 대신에, BeginXXX 메소드를 호출합니다. 이것은 함수로 전달된 파라미터에서 입력 요청을 직렬해제(deserialize)합니다. 그러나 여기서는 BeginXXX메소드로 여분의 AsyncCallback파라메터로써 내부 콜백 함수에 대한 포인터를 전달합니다.

이러한 접근은 웹 서비스 클라이언트 응용 프로그램에서 .NET Framework에 있는 비동기적 프로그래밍 페러다임과 비슷합니다. 비동기적 웹 서비스 호출에 대한 클라이언트 지원의 경우에, 클라이언트 컴퓨터에 대한 쓰레드를 블록처리하는 것에서 자유로울 수 있으며, 반면에 서버 쪽에서도 서버에서의 쓰레드를 블록처리하지 않고 사용합니다. 여기에는 두 가지 다른 점이 있습니다. 첫 번째로 직접 BeginXXXEndXXX 함수를 호출하는 코드를 작성하는 것 대신에, ASMX핸들러가 대신 이들을 호출해 줍니다. 두 번째로, Visual Studio .NET "웹 참조 추가"마법사나 WSDL.EXE를 사용해서 생성된 코드를 사용하는 것 대신에 BeginXXXEndXXX 함수에 대한 코드를 작성할 수 있습니다. 그러나, 결과적으로 다른 어떤 작업을 수행할 수 있도록 쓰레드를 자유롭게 하는 것은 동일합니다.

ASMX핸들러가 서버의 BeginXXX 함수를 호출한 후에, 받게 되는 어느 다른 요청들을 처리할 수 있도록 프로세스의 쓰레드 풀로 쓰레드를 반환합니다. ASMX 핸들러는 BeginXXX함수로 전달된 콜백 함수가 요청에 대한 처리를 마치고 호출되기까지 대기하게 됩니다.

한번 콜백 함수가 호출되면, ASMX 핸들러는 웹 메소드가 수행하기에 필요한 어떤 처리를 완료할 수 있도록 EndXXX 함수를 호출하게 되며, 그리고 반환 데이터는 SOAP응답 안에 직렬화되도록 제공됩니다. EndXXX함수가 반환된 후 응답이 보내지며 요청에 대한 HttpContext가 해지됩니다.

단순한 비동기 웹 메소드

비동기 웹 메소드를 설명하기 위해서, 필자는 아래에 보여준 코드처럼 LengthyProcedure라고 불리는 단순한 동기 메소드부터 시작합니다. 우리는 어떻게 비동기적으로 동일한 것을 처리하는 지를 볼 것입니다. LengthyProcedure는 수천 분의 몇 초 동안만 블록킹 됩니다.

[WebService]
public class SyncWebService : System.Web.Services.WebService
{
    [WebMethod]
    public string LengthyProcedure(int milliseconds) 
    { 
        System.Threading.Thread.Sleep(milliseconds);
        return "Success"; 
    }
}

이제 우리는 LengthyProcedure를 비동기 웹 메소드로 변환합니다. 우리는 반드시 BeginLengthyProcedure 함수를 생성해야 하며 그리고 앞에서 기술한 것처럼 EndLengthyProcedure 함수를 생성해야 합니다. 우리의 BeginLengthyProcedureIAsyncResult 인터페이스를 반환해야 함을 기억해야 합니다. 이 경우에 필자는 우리의 BeginLengthyProcedure가 위임자(delegate)를 사용하는 비동기적 메소드 호출을 하도록 하며 그 위임자에 대해 BeginInvoke 메소드를 갖도록 하려 합니다. 콜백 함수는 우리의 델리게이트에서 BeginInvoke 메소드를 통해 처리될 수 있도록 BeginLengthyProcedure로 전달되며, BeginInvoke로부터 반환되는 IAsyncResultBeginLenthyProcedure 메소드에서 반환됩니다.

EndLengthyProcedure는 우리의 델리게이트가 완료될 때 호출됩니다. 우리는 IAsyncResult에서 전달된 델리게이트에서 EndInvoke메소드를 호출하며 EndLenghyProcedure호출에 대한 입력으로써 받게 됩니다. 반환된 문자열은 우리의 웹 메소드로부터 반환된 문자열이 됩니다. 여기에 코드가 있습니다:

[WebService]
public class AsyncWebService : System.Web.Services.WebService
{
    public delegate string LengthyProcedureAsyncStub(
        int milliseconds);

    public string LengthyProcedure(int milliseconds) 
    { 
        System.Threading.Thread.Sleep(milliseconds);
        return "Success"; 
    }

    public class MyState 
    { 
        public object previousState; 
        public LengthyProcedureAsyncStub asyncStub; 
    }

    [ System.Web.Services.WebMethod ]
    public IAsyncResult BeginLengthyProcedure(int milliseconds, 
        AsyncCallback cb, object s)
    {
        LengthyProcedureAsyncStub stub 
            = new LengthyProcedureAsyncStub(LengthyProcedure);
        MyState ms = new MyState();
        ms.previousState = s; 
        ms.asyncStub = stub;
        return stub.BeginInvoke(milliseconds, cb, ms);
    }
  
    [ System.Web.Services.WebMethod ]
    public string EndLengthyProcedure(IAsyncResult call)
    {
        MyState ms = (MyState)call.AsyncState;
        return ms.asyncStub.EndInvoke(call);
    }
}

비동기 웹 메소드가 사용될 때

응용 프로그램에 비동기적 웹 메소드를 사용할지를 결정해야 할 때 고려해야 할 몇 가지 문제가 있습니다. 첫 번째로, 호출에 대해 BeginXXX 함수는 IAsyncResult 인터페이스를 반환해야 합니다. IAsyncResult는 스트림, Microsoft Windows Sockets호출, 파일 I/O를 실행, 다른 하드웨어 디바이스와 교류, 비동기적 메소드의 호출, 그리고 물론 다른 웹 서비스를 호출하는 것과 같은 다양한 비동기적 I/O작업들로부터 반환됩니다. 이러한 종류의 비동기적 작업들 중의 하나로부터 IAsyncResult를 얻기를 원한다면, BeginXXX 함수로부터 반환할 수 있습니다. 다른 옵션은 IAsyncResult 인터페이스를 구현하는 고유의 클래스를 생성하는 것인데, 앞에서 언급한 I/O 구현중의 하나를 포장하는 것 이상을 해야만 합니다.

우리가 언급했던 비동기적 작업들 중 대부분의 경우, 백그라운드 비동기적 호출을 감싸는 비동기적 웹 메소드의 사용을 주의 깊게 만들고 더 효율적인 웹 서비스 코드로 결과를 주게 됩니다. 위임자를 사용하는 비동기적 메소드 호출을 사용할 경우 예외가 있습니다. 위임자는 프로세스의 쓰레드 풀에 있는 쓰레드를 실행해서 비동기적 메소드 호출을 하도록 합니다. 불행히도, 이러한 것들은 입력된 요청들을 서비스하기 위해 ASMX 핸들러에서 사용된 것과 동일한 쓰레드여야 합니다. 하드웨어나 네트워킹 리소스에 대한 실제 I/O 오퍼레이션을 수행하는 호출들과는 달리, 위임자를 사용하는 비동기적 메소드 호출은 실행 중에 프로세스 쓰레드 중의 하나를 여전히 블록킹하게 됩니다. 원래 쓰레드를 블록킹하고 동기적으로 실행되는 웹 메소드를 갖도록 해야 합니다.

다음의 예제는 최후위 웹 서비스를 호출하는 비동기적 웹 메소드를 보여줍니다. 비동기적으로 실행되는 WebMethod 속성으로 BeginGetAgeEndGetAge 메소드를 표시합니다. 이러한 비동기적 웹 메소드에 대한 코드는 반환될 정보를 얻기 위해 UserInfoQuery라 불리는 최후위 웹 메소드를 호출합니다. UserInfoQuery에 대한 호출은 비동기적으로 실행되며 BeginGetAge 메소드로 전달되는 AsyncCallback 함수를 전달합니다. 이것은 최후위 요청이 완료될 때 호출되는 내부 콜백 함수가 실행되도록 합니다. 콜백 함수는 요청을 완료하도록 EndGetAge 메소드를 호출합니다. 이 경우 코드는 앞에서의 예제보다 더 간단해지며, 그리고 우리의 중간 계층의 웹 메소드 요청을 서비스하는 동일한 쓰레드 풀에서 최후위 프로세스을 실행하지 않는 추가적인 이점을 가지게 됩니다.

[WebService]
public class GetMyInfo : System.Web.Services.WebService
{
    [WebMethod]
    public IAsyncResult BeginGetAge(AsyncCallback cb, Object state)
    {
        // 비동기적인 웹 서비스 호출
        localhost.UserInfoQuery proxy 
            = new localhost.UserInfoQuery();
        return proxy.BeginGetUserInfo("User's Name", 
                                      cb, 
                                      proxy);
    }

    [WebMethod]
    public int EndGetAge(IAsyncResult res)
    {
        localhost.UserInfoQuery proxy 
            = (localhost.UserInfoQuery)res.AsyncState;
        int age = proxy.EndGetUserInfo(res).age;
        //  웹 서비스 호출로부터의 결과에 추가적인 프로세싱을 수행합니다. 
        return age;
    }
}

웹 메소드 내부에서 일어나는 가장 공통적인 형태의 I/O작업중의 하는 SQL 데이터베이스에 대한 호출입니다. 불행히도, Microsoft ADO.NET은 2002년 현재 좋은 비동기적인 호출 메카니즘을 가지고 있지 않으며, 단순하게 비동기적인 위임자 호출 안에서 SQL호출을 감싸는 것은 효율성 부분에서 도움이 되지 않습니다. 웹 서비스로 데이터베이스를 노출시키기를 원한다면 Microsoft SQL Server 2000 Web Services Toolkit (영문)을 사용을 고려해 볼 수 있습니다. 데이터베이스를 업데이트하거나 질의하는 비동기적인 웹 서비스를 호출하기 위해서 .NET Framework의 지원을 받을 수 있습니다.

웹 서비스 호출을 통해 SQL을 액세스하는 것은 많은 최후위 리소스들에 사용해야 할 방법 중 하나입니다. 만일 유닉스 서버와 커뮤니케이션을 하기 위해 TCP소켓을 사용한다면, 또는 적절한 데이터베이스 드라이버들을 통해 다른 SQL플랫폼중의 어던 것을 액세스한다면 - 또는 DCOM을 사용해서 액세스하는 리소스를 가지고 있다면 -웹 서비스로써 리소스를 노출시켜주는 현 시점에서 가능한 다양한 웹 서비스 툴킷들의 사용을 고려해 볼 수 있습니다.

이러한 접근법을 취하는 것의 장점 중의 하나는, .NET Framework에서 비동기적 웹 서비스 호출과 같은 클라이언트 쪽 웹 서비스 인프라구조에서의 장점들을 취하는 것입니다. 비용이 들지 않는 비동기적 호출을 얻는다면, 클라이언트 액세스 메커니즘은 비동기적 웹 메소드와 함께 효율적으로 작업할 수 있게 될 겁니다.

비 동기적 웹 메소드를 사용해서 데이터를 집계

오늘날의 많은 웹 서비스들은 최후위 쪽에 있는 다중의 리소스들을 액세스하며 최전위 웹 서비스에 대한 정보들을 집계합니다. 심지어 웹 메소드 모델을 더욱 복잡하게 만드는 여러 개의 최후위 리소스들을 호출하는 것은, 상당한 양의 효율성을 얻게 됩니다.

서비스 A와 서비스 B인, 두 개의 최후위 웹 서비스를 호출하는 웹 메소드가 있다고 합시다. BeginXXX 함수로부터, 비동기적으로 서비스 A를 호출하고 서비스 B를 비동기적으로 호출합니다. 당신은 이러한 비동기적 호출의 각각에 대해서 고유의 콜백 함수를 전달할 수 있습니다. 서비스 A와 서비스 B 양쪽에서 결과를 받은 후에 웹 메소드의 완료를 자동 동작시키기 위해, 당신이 제공한 콜백 함수는 양쪽의 요청이 완료되었는지를 검사하며, 반환된 데이터에 대한 처리를 실행하며, 그리고 BeginXXX 함수에 대해 전달된 콜백 함수를 호출하게 됩니다. 이것은 비동기적 웹 메소드가 완료되도록 반환되는, EndXXX 함수를 호출하도록 자동 동작시킵니다.

결론

비동기적인 웹 메소드는 프로세스 쓰레스 풀 안에 귀중한 쓰레드가 아무것도 하지 않으면서 블록되도록 두지 않고 ASP.NET 웹 서비스에서 최후위 서비스를 호출하는 효율적인 메커니즘을 제공합니다. 최후위 리소스들에 대한 비동기적인 요청들과의 결합하여, 서버는 그들의 웹 메소드들을 최대로 처리할 수 있게 됩니다. 고성능의 웹 서비스 응용 프로그램을 개발하기 위해서는 이러한 접근방법을 고려해 보아야 합니다.


저자에 대해

Matt Powell 은 SOAP Toolkit 1.0을 개발을 도운, MSDN 구조화 샘플 팀의 멤버입입니다. Matt는 MMicrosoft출판사의 Running Microsoft Internet Information Server 의 저자미여, 많은 잡지 기사들을 집필했습니다.

출처 : MSDN - http://ms.inposti.com/korea/msdn/library/ko-kr/dnservice/html/service10012002.aspx

Posted by 굥쓰
Study/MSDN2008. 2. 16. 15:08
Visual Studio와 Subversion의 통합

Subversion은 지난 수년간 인기를 얻어온 공개 소스 소스 제어 시스템입니다. Subversion은 단순하고 사용자에게 익숙한 방식으로 분기, 태그 지정 및 병합과 같은 여러 가지 일반적인 소스 제어 기능을 처리합니다. Subversion이 인기를 얻고 있는 이유는 무료 공개 소스이고, 설치와 사용이 쉬우며, TortoiseSVN과 같은 탁월한 도구가 있기 때문입니다. Windows® 탐색기 확장 기능인 TortoiseSVN을 사용하면 별도의 도구를 사용하지 않고도 표준 탐색기 창에서 바로 모든 소스 제어 기능을 수행할 수 있습니다.

SourceForge에서는 Subversion 호스팅을 제공하기 시작했으며, CodePlex에서도 TortoiseSVN을 사이트에서 사용할 수 있도록 Subversion 에뮬레이션을 제공합니다. Subversion으로 전환하는 일부 .NET 회사에서 가장 자주 놓치는 기능 중 하나로 Visual Studio와의 밀접한 통합이 있지만 이러한 통합을 가능하게 해 주는 다른 유명한 소스 제어 시스템이 있습니다.

Visual Studio와 Subversion 간의 탁월한 통합 기능을 제공하는 Visual Studio 추가 기능인 VisualSVN을 사용해 보십시오. VisualSVN을 사용하면 Visual Studio에서 제공하는 솔루션 탐색기의 각 파일 옆에 쉽게 알 수 있는 마커가 표시됩니다(솔루션이 Subversion 리포지토리에 저장되어 있어야 함). 이 마커는 파일이 수정되었거나 수정되지 않았거나 충돌이 발생할 때 표시됩니다. 파일을 마우스 오른쪽 단추로 클릭한 다음 변경 내용을 보거나 이전 상태로 되돌리거나 업데이트하거나 커밋할 수 있습니다.

VisualSVN 메뉴를 사용하여 전체 프로젝트의 변경 내용을 관리할 수 있습니다. VisualSVN 메뉴에는 리포지토리 탐색기, 패치 만들기 및 적용, Subversion 로그 보기, 리포지토리 분기, 병합 및 전환과 같은 일반적인 TortoiseSVN 기능에 대한 바로 가기도 있습니다.

가장 중요한 기민성 개념 중 하나는 초기에 자주 체크 인하는 것입니다. 가능한 한 신속하게 통합하여 잠재적인 병합 문제를 찾을 수 있으며, 지속적인 통합을 구현하는 경우 모든 코드가 빌드되고 테스트가 실행됩니다. Visual Studio와 밀접하게 통합되어 있는 VisualSVN은 수정한 후 아직 체크 인하지 않은 변경 내용에 대한 알림을 지속적으로 제공하므로 초기에 자주 체크 인할 수 있습니다. 이러한 변경 내용을 Visual Studio에서 직접 체크 인할 수 있으므로 더 이상 미룰 이유가 없습니다.

발췌 : http://msdn.microsoft.com/msdnmag/issues/08/LA/Toolbox/default.aspx?loc=ko#S2

Posted by 굥쓰