Search code examples
c#.netrefactoringtaskcompletionsource

Use TaskCompletionSource with generic Type as parameter


I am currently refactoring a bit of code which has two extremly similar methods. Both methods use a TaskCompletionSource with a bool on one side and a string on the other.

Now both of those methods have a bit of code that reads the Task of the respective TaskCompletionSource and awaits it afterwards.

Is there a way to refactor this codebit into a method where I can pass the TaskCompletionSource as a parameter with a generic Type, so that I can use it in both methods and thus reduce my code?

Simplified example code:

public void BoolMethod(){
    TaskCompletionSource<bool> boolTCS = new TaskCompletionSource<bool>();
    Task? taskToAwait = null;
    
    [...do shared code...]
    taskToAwait = boolTCS.Task;
    [...do shared code...]
    await taskToAwait;
    
    
    [...do method specific code...]
}

public void StringMethod(){
    TaskCompletionSource<string> stringTCS = new TaskCompletionSource<string>();
    Task? taskToAwait = null;
    
    [...do shared code...]
    taskToAwait = stringTCS.Task;
    [...do shared code...]
    await taskToAwait;
    
    
    [...do method specific code...]
}

How I thought it worked / What I tried:

public Task? DoSharedCode(TaskCompletionSource<T> tcs){
    Task? taskToAwait = null;
    
    [...do shared code...]
    taskToAwait = tcs.Task;
    [...do shared code...]
    return taskToAwait;

}

public void StringMethod(){
    TaskCompletionSource<string> stringTCS = new TaskCompletionSource<string>();
    
    await DoSharedCode(stringTCS);
    
    [...do method specific code...]
}

This gets me an Error CS1503;

Could anyone tell me if this is possible and if yes, what I did wrong?


Solution

  • If you want to use a generic type you need to declare the type in the method or class, i.e:

    public Task? DoSharedCode<T>(TaskCompletionSource<T> tcs){
        Task? taskToAwait = null;
        
        [...do shared code...]
        taskToAwait = tcs.Task;
        [...do shared code...]
        return taskToAwait;
    
    }
    

    But if you are not using the result from the task, why use different types for your TaskCompletionSource? Where do you set the task completion source result? Why create the intermediate taskToAwait instead of just return tcs.Task? The posted example do not make a lot of sense to me as it is.