Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping a series of asynchronous calls with a synchronous method with a return value

My current code uses series of asynchronous processes that culminate in results. I need to wrap each of these in such a way that each is accessed by a synchronous method with the result as a return value. I want to use executor services to do this, so as to allow many of these to happen at the same time. I have the feeling that Future might be pertinent to my implementation, but I can't figure out a good way to make this happen.

What I have now:

public class DoAJob {
  ResultObject result;

  public void stepOne() {
    // Passes self in for a callback
    otherComponent.doStepOne(this);
  }

  // Called back by otherComponent once it has completed doStepOne
  public void stepTwo(IntermediateData d) {
    otherComponent.doStepTwo(this, d);
  }

  // Called back by otherComponent once it has completed doStepTwo
  public void stepThree(ResultObject resultFromOtherComponent) {
    result = resultFromOtherComponent;
  //Done with process
  }
}

This has worked pretty well internally, but now I need to map my process into a synchronous method with a return value like:

public ResultObject getResult(){
  // ??? What goes here ???
}

Does anyone have a good idea about how to implement this elegantly?

like image 911
irondwill Avatar asked Apr 04 '13 15:04

irondwill


People also ask

Should I expose synchronous wrappers for asynchronous methods?

In my discussion of “async over sync,” I strongly suggested that if you have an API which internally is implemented synchronously, you should not expose an asynchronous counterpart that simply wraps the synchronous method in Task. Run.

Can we call synchronous method from another asynchronous method?

Yes, We can call a synchronous method inside a future method. Both will run on Asynchronous Only.

How do you make a synchronous call asynchronous?

The simplest way to execute a method asynchronously is to start executing the method by calling the delegate's BeginInvoke method, do some work on the main thread, and then call the delegate's EndInvoke method. EndInvoke might block the calling thread because it does not return until the asynchronous call completes.

What is the role of sync wrapper?

Wraps asynchronous functions in order to make them synchronous based on if a “sync” feature is enabled. This is useful when writting http clients as you can write async methods and wrap them for use in synchronous code bases automatically.


1 Answers

If you want to turn an asynchronous operation (which executes a callback when finished), into a synchronous/blocking one, you can use a blocking queue. You can wrap this up in a Future object if you wish.

  1. Define a blocking queue which can hold just one element:

    BlockingQueue<Result> blockingQueue = new ArrayBlockingQueue<Result>(1);

  2. Start your asynchronous process (will run in the background), and write the callback such that when it's done, it adds its result to the blocking queue.

  3. In your foreground/application thread, have it take() from the queue, which blocks until an element becomes available:

    Result result = blockingQueue.take();

I wrote something similar before (foreground thread needs to block for an asynchronous response from a remote machine) using something like a Future, you can find example code here.

like image 73
npgall Avatar answered Sep 19 '22 17:09

npgall