I am changing the library to add async methods. From Should I expose synchronous wrappers for asynchronous methods? he claims that I should just write a wrapper around Task.Result when calling the synchronous method. But how do I not need to duplicate a lot of code between asynchronous methods and synchronization methods, since we want to save both options in the library?
For example, the library currently uses the TextReader.Read method. In terms of asynchronous change, we would like to use the TextReader.ReadAsync method. Since this is the basis of libraries, it seems to me that I will need to duplicate a lot of code between synchronous and asynchronous methods (it is desirable that DRY code be as possible). Or I need to reorganize them in the PreRead and PostRead , which seem to clutter up the code and what TPL is trying to fix.
I am thinking of just wrapping the TextReader.Read method in Task.Return() . Even though this is a task, improvements from TPL should not include it in another thread, and I can still use async, expecting most of the code as usual. Would it be nice if the synchronous wrapper was just Task.Result or Wait() ?
I looked at other examples in the .net library. StreamReader duplicate code between asynchronous and asynchronous. MemoryStream does Task.FromResult .
Also planning everywhere, I could add ConfigureAwait(false) , as it is just a library.
Update:
What I'm talking about duplicate code,
public decimal ReadDecimal() { do { if (!Read()) { SetInternalProperies() } else { return _reader.AsDecimal(); } } while (_reader.hasValue) } public async Task<decimal> ReadDecimalAsync() { do { if (!await ReadAsync()) { SetInternalProperies() } else { return _reader.AsDecimal(); } } while (_reader.hasValue) }
This is a small example, but you can see that the only code change is wait and task.
To be clear, I want to use the async / await and TPL code in the library, but I still need to use the old synchronization methods as well. I am not going to just Task.FromResult() use synchronization methods. What I thought was with a flag that says I want the synchronization method and at the root to check the flag in something like
public decimal ReadDecimal() { return ReadDecimalAsyncInternal(true).Result; } public async Task<decimal> ReadDecimal() { return await ReadDecimalAsyncInternal(false); } private async Task<decimal> ReadDecimalAsyncInternal(bool syncRequest) { do { if (!await ReadAsync(syncRequest)) { SetInternalProperies() } else { return _reader.AsDecimal(); } } while (_reader.hasValue) } private Task<bool> ReadAsync(bool syncRequest) { if(syncRequest) { return Task.FromResult(streamReader.Read()) } else { return StreamReader.ReadAsync(); } }