Tải bản đầy đủ - 0 (trang)
Chapter 11. Parallel, Asynchronous, and Real-Time Data Operations

Chapter 11. Parallel, Asynchronous, and Real-Time Data Operations

Tải bản đầy đủ - 0trang

Here are the steps for handling an asynchronous request . ASP.NET grabs a thread from

the thread pool and executes it to handle the incoming request. After invoking the

ASP.NET MVC action asynchronously, it returns the thread to the thread pool so it

can handle other requests. The asynchronous operation executes on a different thread;

when it’s done it notifies ASP.NET. ASP.NET grabs a thread (which may be different

than the original thread) and invokes it to finish processing the request. This includes

rendering the process (output).



Creating an Asynchronous Controller

Creating an asynchronous controller is fairly easy. Simply inherit from the AsyncCon

troller base class, which provides methods to help manage asynchronous request

processing:

public class SearchController : AsyncController

{

}



An asynchronous controller is required because the SearchForBids() method uses a

complex LINQ query, which could take several seconds to process:

public ActionResult SearchForBids(DateTime startingRange, DateTime endingRange)

{

var bids = _repository

.Query(x => x.Timestamp >= startingRange && x.Timestamp ↵

<= endingRange)

.OrderByDescending(x => x.Timestamp)

.ToArray();

}



return Json(bids, JsonRequestBehavior.AllowGet);



Prior to ASP.NET MVC 4, the following conventions had to be followed to create

asynchronous controller methods:

Action Name Async

The method has to return void; it starts the asynchronous process

Action Name Completed

This method is called when the asynchronous process is complete; it handles returning the ActionResult

Here is the updated SearchForBids() method that has been set up to use Background

Worker to asynchronously search for bids:

public void SearchForBidsAsync(DateTime startingRange, DateTime endingRange)

{

AsyncManager.OutstandingOperations.Increment();

var worker = new BackgroundWorker();

worker.DoWork += (o, e) => SearchForBids(Id, e);



234 | Chapter 11: Parallel, Asynchronous, and Real-Time Data Operations



www.it-ebooks.info



worker.RunWorkerCompleted += (o, e) =>

{

AsyncManager.Parameters["bids"] = e.Result;

AsyncManager.OutstandingOperations.Decrement();

};

worker.RunWorkerAsync();

}

private void SearchForBids(string Id, DoWorkEventArgs e)

{

var bids = _repository

.Query(x => x.Timestamp >= startingRange && x.Timestamp <= endingRange)

.OrderByDescending(x => x.Timestamp).ToList();

}



e.Result = bids;



public ActionResult SearchForBidsCompleted(IEnumerable bids)

{

return Json(bids, JsonRequestBehavior.AllowGet);

}



Note how AsyncManager.OutstandingOperations is Increment prior to the operation being started and Decrement when the operation is completed. This is required to notify

ASP.NET about how many pending operations the method contains. When the value

of the OutstandingOperations property reaches zero, ASP.NET completes the asynchronous processing of the method and calls SearchForBidsCompleted().

That’s a lot of code. Fortunately, version 4.5 of the .NET Framework introduces the

new async and await keywords to help make asynchronous programming much

simpler.

See the following link to get additional details about asynchronous

programming in .NET 4.5: http://msdn.microsoft.com/en-us/library/

hh191443(v=vs.110).aspx.



Here is the final SearchForBids() method, updated to use the new asynchronous keywords:

public async Task SearchForBids(string Id)

{

var bids = await Search(Id);

return Json(bids, JsonRequestBehavior.AllowGet);

}

private async Task> Search(string Id)

{

var bids = _repository

.Query(x => x.Timestamp >= startingRange && x.Timestamp <= endingRange)



Asynchronous Controllers | 235



www.it-ebooks.info



}



.OrderByDescending(x => x.Timestamp).ToList();

return bids;



Controller actions that return a Task instance can be configured with a timeout. To set

a timeout, use the AsyncTimeout attribute. The following example shows a controller

action that has a timeout of 2,500 milliseconds. If the timeout occurs, the AjaxTimedOut view will be returned:

[AsyncTimeout(2500)]

[HandleError(ExceptionType = typeof(TaskCanceledException), View = "AjaxTimedOut")]

public async Task SearchForBids(string Id)

{

}



Choosing When to Use Asynchronous Controllers

There are no hard and fast rules regarding when to use asynchronous actions. The

following guidelines will help make your decision about when to take advantage of

asynchronous actions.

These are the typical scenarios where it’s best to use synchronous actions:

• Simple and short-running operations

• Cases where simplicity is more important than efficiency

• CPU-intensive operations (asynchronous actions provide no benefit and can add

overhead for such operations)

These are the typical scenarios where it’s preferable to use asynchronous actions:

• Long-running operations that are causing a bottleneck in performance

• Network- or I/O-intensive operations

• When the application requires the ability for users to cancel a long-running operation



Real-Time Asynchronous Communication

The World Wide Web is an ever-changing environment; application models that

worked even a few months ago may no longer meet user expectations. Instead of building monolithic web applications with dozens of pages, more and more developers are

building applications using a single-page architecture approach, or a small set of pages

that are dynamically updated in real time.

The adoption of real-time data techniques can be traced to the explosion of social

networking and mobile devices. In today’s world, people are always on the go, and they

want instant access to the latest information, whether it’s their favorite team’s sports

score, the price of a hot stock, or new posts from their friends. And since more people

are accessing websites using mobile devices, it’s important that a web application be

236 | Chapter 11: Parallel, Asynchronous, and Real-Time Data Operations



www.it-ebooks.info



able to detect network availability and gracefully handle the features of web browsers

across a multitude of different devices.



Comparing Application Models

The traditional web application model relies on synchronous communication. As a user

interacts with the application, the host web browser makes requests to the server, which

processes them and returns a snapshot of the current state of the application. Since

there is no guarantee that the user will trigger another request, there is a high potential

that the content the user is looking at may become stale, leading to data conflict issues.

Using techniques like AJAX only addresses part of the problem. In most cases the user

still needs to trigger a request. AJAX relies on the traditional request/response approach, where interactions are very transactional and atomic, and anything that

changes outside of the current transaction cannot be communicated—in order to get

“back in sync,” another request must be made. As such, this approach does not handle

real-time updates very well. More advanced techniques that create longer-lived conversations between the server and the browser must be applied in order to support such

scenarios.

Let’s take a look at the different real-time communication models available. Keep in

mind that the HTTP protocol is designed around the request/response communication

pattern and does not directly support the ability for the server to communicate with a

client without the client first submitting a request.



HTTP Polling

Figure 11-1 involves creating an ongoing conversation by mimicking a “constant connection” with the server based on a series of standard AJAX requests. This is usually

achieved by sending AJAX requests on a regular basis using a JavaScript timer.



Figure 11-1. HTTP polling



Figure 11-1 shows polling in action. The most important thing about this technique is

that the browser creates a new request immediately after each existing request is complete (regardless of whether the completed request actually succeeded or contained

data), so fault tolerance is effectively built in.

Real-Time Asynchronous Communication | 237



www.it-ebooks.info



As such, polling is one of the most reliable and fail safe “real-time” communication

methods—but this reliability comes at a cost. As Figure 11-2 shows, polling produces

a relatively huge amount of network traffic and server load, especially considering requests are processed regardless of whether the server has any updates (so many, if not

most, of the requests will return no data).



Browser support

Polling utilizes various browser technologies that have been around essentially since

the origin of the graphical web browser, so it works anywhere and everywhere that

JavaScript is enabled.



Downsides

Polling has several drawbacks. The inordinate number of requests compared to the

amount of actual data that is transferred makes this technique incredibly wasteful.

Client requests and server events are not always in sync; it’s possible for multiple server

events to occur between client requests. If not kept in check, this approach can inadvertently create a denial-of-service attack on your own servers!



HTTP Long Polling

The HTTP Long Polling technique is primarily a server-side implementation wherein

the browser makes an AJAX request to the server to retrieve data, and the server keeps

the connection open until it has data to return. This is in stark contrast to the traditional

request/response approach, wherein the server immediately responds that it has no

data if it is unable to supply the data when it receives the AJAX request.



Figure 11-2. HTTP long polling



Long polling entails making a request in anticipation of a possible future server event.

Instead of the server immediately returning a response, the incoming request is blocked

until a server event occurs or the request times out (or the connection is broken). Then

the client must initiate a new long polling request in order to start the next interaction

and continue to retrieve updated data.

238 | Chapter 11: Parallel, Asynchronous, and Real-Time Data Operations



www.it-ebooks.info



Browser support

Because there are many different long polling implementations, this technique works

—with varying degrees of reliability—on all browsers.



Downsides

Because the Internet infrastructure is built around simple HTTP request/response interactions and not built to handle long-lived connections, long polling requests are not

reliable, because they tend to get disconnected frequently. Broken connections are actually part of the long polling workflow, so handling them is the same as handling a

successful request: you start a new request. However, this complexity adds to the unreliability of the approach as a whole.

Further, as with most widely supported techniques, long polling implementations are

often limited to the lowest common feature set that all browsers support, which

amounts to a simple HTTP GET request (the URL that can be applied to an IFRAME or













To receive a message, create an instance of the hub’s JavaScript proxy class and subscribe to one or more of the methods defined by the Clients dynamic object. Call

$.connection.hub.start() to initialize the communication channel between the client

and server:

$(function () {

// Proxy created on the fly

var proxy = $.connection.ebuyCustomHub;

// Declare callback function

proxy.displayMessage = function(message) {

$('#messages').append('
  • ' + message + '
  • ');

    };



    });



    // Start the connection

    $.connection.hub.start();



    To send a message, call one of the public methods defined for the hub (e.g., sendMes

    sage()).

    connection.sendMessage("Hello SignalR!");



    Real-Time Asynchronous Communication | 243



    www.it-ebooks.info



    Hubs are very extensible. It’s easy to create multiple different methods for handling

    different types of server events. Also, in addition to sending string-based messages, it’s

    possible to send JSON objects between the client and the server.

    Here is an example of a hub that supports multiple message types:

    public class EbuyCustomHub : Hub

    {

    public void PlaceNewBid(string jsonObject)

    {

    var serializer = new JavaScriptSerializer();

    var bid = serializer.Deserialize(jsonObject);

    }



    }



    Clients.newBidPosted(bid);



    public void AuctionClosed(Auction auction)

    {

    Clients.auctionClosed(auction);

    }



    Out of the box .NET types sent to the Clients object will automatically

    be serialized into JSON. Incoming messages require manual deserialization using a JSON serializer.



    The following code snippet shows the JavaScript used in the Ebuy reference application

    for receiving and sending notifications about new bids. To send a new bid, a JSON

    object needs to be created and serialized into a string; the incoming hub event parameter

    (bid) will be passed in as a JSON object:

    $(function () {

    // Proxy created on the fly

    var proxy = $.connection.ebuyCustomHub;

    // Declare server callback methods

    proxy.newBidPosted = function (bid) {

    $('#bids').append('
  • Auction: ' + bid.Auction.Title + ' Latest Bid: ' ↵

    + bid.Amount.Value + '
  • ');

    };

    // Start the connection

    $.connection.hub.start();



    });



    $("#postBid").click(function () {

    var bidToPost = GetBid();

    proxy.placeNewBid(bidToPost);

    });



    function GetBid() {



    244 | Chapter 11: Parallel, Asynchronous, and Real-Time Data Operations



    www.it-ebooks.info



    Tài liệu bạn tìm kiếm đã sẵn sàng tải về

    Chapter 11. Parallel, Asynchronous, and Real-Time Data Operations

    Tải bản đầy đủ ngay(0 tr)

    ×