Reputation: 153
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
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
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