Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return the same value for multiple function calls while a request is ongoing using async/await

Given the following function:

public async Task<int> GetValue() {
    var value = await GetValueFromServer();
    return value;
}

I would like to accomplish this. The function GetValue() can be called from different parts of the program. While GetValueFromServer() is running I don't want to initiate another call to it. All calls to to GetValue() while GetValueFromServer() is running should return the same value and not initiate another call. A call to GetValue() while GetValueFromServer() is not running should initiate a new call to GetValueFromServer().

An example:

0.0: var a = await GetValue()
0.1: call to GetValueFromServer()
0.3: var b = await GetValue();
0.6: var c = await GetValue();
0.7: GetValueFromServer() returns 1 
0.9: var d = await GetValue();
1.0: call to GetValueFromServer()
1.3 GetValueFromServer() returns 2

The calls to GetValue() at 0.0, 0.3 and 0.6 should only trigger a single call to GetValueFromServer(). All three callers should receive the same value. The call to GetValue() at 0.9 should trigger another call to GetValueFromServer().

I'm still stuck in Objective-C thinking where I would use blocks to accomplish this. I would queue up the blocks and when the request to the server returns call each block that was queued.

- (void)getValue:(void(^)(int value))block {
    [_runningBlocks addObject:[block copy]];
    if (_runningBlocks.count > 1) {
        return;
    }

    [self getValueFromServer:^(int value) {
        for (void(^)(int)b in _runningBlocks) {
           b(value);
        }
        [_runningBlocks removeAllObjects];
    ];
 }

Now I would like to accomplish the same thing but using the async/await pattern. This is for use in a Windows Phone 8.1 (RT) app and if possible I would like to avoid a third party library/framework.

like image 259
Robert Höglund Avatar asked Apr 17 '15 07:04

Robert Höglund


1 Answers

You need to share the same task in order to return the same value(You need to share the state). To do that, you need to synchronize the access.

Following should be more than enough.

private object padLock = new object();
private Task<int> executingTask;
public async Task<int> GetValue() 
{  
    lock(padLock)
    {
        if (executingTask  == null || executingTask.IsCompleted)
            executingTask= GetValueFromServer();
    }

    var value = await executingTask;
    return value;
}
like image 163
Sriram Sakthivel Avatar answered Oct 24 '22 05:10

Sriram Sakthivel