Concurrent events: simplifying APM with AsyncEnumerator

Source: Internet
Author: User
Tags foreach apm continue thread

Directory

Using the AsyncEnumerator class

Architecture of the AsyncEnumerator

Use the wait and Inbox counters

Thread-Safe Distortion

See more information

In the previous column (Concurrency event: simplifying APM via C #), I talked about the idea of simplifying asynchronous programming with the new C # language features (anonymous, lambda, and iterators). At the end of the column, I explained how to use the C # iterator to complete asynchronous programming using the synchronous programming model. Figure 1 shows the sample iterator. However, the code of the iterator cannot be executed by using only the regular C # foreach statement, because this code is always executed by the thread that calls foreach, and is performed continuously and does not pause to complete the asynchronous I/O operation.

In this column, I'll introduce my AsyncEnumerator class, which intelligently drives iterators so that different thread pool threads can execute code at different times, and I can ensure that the iterator does not perform the next iteration until it completes an asynchronous I/O operation. In addition, I'll introduce the architecture of the AsyncEnumerator class and how it works.

Using the AsyncEnumerator class

The following is the definition of the AsyncEnumerator class:

public class AsyncEnumerator {
  // Methods called by code outside of the iterator
  public AsyncEnumerator();
  public void Execute(IEnumerator<Int32> enumerator);
  // Methods called by code inside the iterator
  public AsyncCallback End();
  public IAsyncResult DequeueAsyncResult();
}

The use of the AsyncEnumerator class is fairly straightforward. First, let's describe how to implement your iterator members, and then describe how to invoke them.

Define the iterator member to accept any parameters that you want, and add an additional parameter, which is a reference to the AsyncEnumerator object. When you return to the Int32 collection, your iterator member must be set to a prototype; in other words, its return type must be ienumerator<int32>.

Then, within the iterator member, each asynchronous operation is started by calling the appropriate BeginXxx method. You know that if you call the BeginXxx method, you must pass it the name of the method that should be called when the asynchronous operation completes.

You can call the end method of the AsyncEnumerator object without having to define your own method. The End method returns a AsyncCallback proxy that identifies the private method defined in the AsyncEnumerator class. Therefore, the code in the AsyncEnumerator object is notified when each asynchronous operation completes. The code then places the IAsyncResult object of the completed operation into the List<iasyncresult> object (which I call Inbox, the Inbox).

In your code, after calling the BeginXxx method, place a yield return statement that returns the number of queued asynchronous operands. In Figure 1, because I call only one BeginXxx method (BeginRead), the yield return statement returns a value of 1. The yield return statement pauses your iterator method and stops executing the code in it.

Figure 1 C # iterator

private static IEnumerator<Int32> ApmPatternWithIterator(
  AsyncEnumerator ae, String pathname) {
  using (FileStream fs = new FileStream(pathname, FileMode.Open,
    FileAccess.Read, FileShare.Read, 8192, FileOptions.Asynchronous)) {
    Byte[] data = new Byte[fs.Length];
    fs.BeginRead(data, 0, data.Length, ae.End(), null);
    yield return 1;
    Int32 bytesRead = fs.EndRead(ae.DequeueAsyncResult());
    ProcessData(data);
  }
}

Later, I'll provide some other examples that let yield return statements not have a value of 1, but for many applications, it's more appropriate to return 1. The number specified in the yield return statement tells the AsyncEnumerator object how many asynchronous operations it needs to complete in order to recover the execution of the iterator. Therefore, when the iterator is paused, all asynchronous operations that you start will continue to complete. After each asynchronous operation is completed, an entry is added to the AsyncEnumerator's inbox. When the number of items in your inbox equals the number you specified in the yield return statement, the AsyncEnumerator object resumes execution of the iterator and allows you to continue executing its code.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.