Alex
Alex

Reputation: 153

how to do it better replace continueWith to async/await in C#

I have C# code:

public class SimpleClass{

    public Task<TestClass> WaitForUserInput(IResource resource, CancellationToken token)
    {
        var button = resource.GetResource();

        var taskCompletionSource = new TaskCompletionSource<UserActionResult>();
        IDisposable cancellationTokenReg = token.Register(
                                      () => taskCompletionSource.SetResult(new TestClass()));

        var taskDisposeTokenUnreg = taskCompletionSource.Task.ContinueWith(
            task =>
                {
                    cancellationTokenReg.Dispose();
                     return task.Result;
                 });

        button.TouchEvent += Subscribe;
        button.Disabled = true;

        return taskDisposeTokenUnreg;
    }
}       

I need replace continueWith to await. And I try in this example:

public class SimpleClass{

    public async Task<TestClass> WaitForUserInput(IResource resource, CancellationToken token)
    {
        var button = resource.GetResource();

        var taskCompletionSource = new TaskCompletionSource<UserActionResult>();
        IDisposable cancellationTokenReg = token.Register(
                                      () => taskCompletionSource.SetResult(new TestClass()));

        var taskDisposeTokenUnreg = await taskCompletionSource.Task
        cancellationTokenReg.Dispose();
        return taskDisposeTokenUnreg.Result;

        button.TouchEvent += Subscribe;
        button.Disabled = true;

        return taskDisposeTokenUnreg;
    }
}     

But taskDisposeTokenUnreg has no field Result and and you can’t write like that await taskCompletionSource.Task.Result. How best to replace this code?

Upvotes: -1

Views: 667

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456407

Your original method has a synchronous signature; all the code in that method (except the delegates) is executed immediately. The ContinueWith delegate is the only code that executes later, after the taskCompletionSource.Task completes. So, to duplicate this behavior, you need to move the ContinueWith delegate to the end of the method, so all the synchronous code executes first just like it did before:

public async Task<TestClass> WaitForUserInput(IResource resource, CancellationToken token)
{
  var button = resource.GetResource();

  var taskCompletionSource = new TaskCompletionSource<UserActionResult>();
  IDisposable cancellationTokenReg = token.Register(
                                      () => taskCompletionSource.SetResult(new TestClass()));

  button.TouchEvent += Subscribe;
  button.Disabled = true;

  var result = await taskCompletionSource.Task;
  cancellationTokenReg.Dispose();
  return result;
}

Once you're using async/await, then you can simplify further by using a using declaration:

public async Task<TestClass> WaitForUserInput(IResource resource, CancellationToken token)
{
  var button = resource.GetResource();

  var taskCompletionSource = new TaskCompletionSource<UserActionResult>();
  using var cancellationTokenReg = token.Register(
                                      () => taskCompletionSource.SetResult(new TestClass()));

  button.TouchEvent += Subscribe;
  button.Disabled = true;

  return await taskCompletionSource.Task;
}

Upvotes: 0

Gabriel Luci
Gabriel Luci

Reputation: 40868

When you use the await operator on a Task, the value you get is the result of the Task.

So in your case, taskDisposeTokenUnreg will already be the UserActionResult value you are looking for. You can just return taskDisposeTokenUnreg.

Upvotes: 1

Related Questions