【问题标题】:how to do it better replace continueWith to async/await in C#如何更好地在 C# 中将 continueWith 替换为 async/await
【发布时间】:2019-12-25 18:23:15
【问题描述】:

我有C# 代码:

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;
    }
}       

我需要将 continueWith 替换为 await。我在这个例子中尝试:

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;
    }
}     

但是taskDisposeTokenUnreg 没有字段Result,而且你不能这样写await taskCompletionSource.Task.Result。 如何最好地替换此代码?

【问题讨论】:

  • var taskDisposeTokenUnreg 应该已经是 Result - 你检查过它的类型吗?

标签: c# async-await task token continuewith


【解决方案1】:

当您在Task 上使用await operator 时,您获得的值是Task 的结果。

因此,在您的情况下,taskDisposeTokenUnreg 已经是您正在寻找的 UserActionResult 值。你可以return taskDisposeTokenUnreg

【讨论】:

    【解决方案2】:

    您的原始方法具有同步签名;该方法中的所有代码(委托除外)都会立即执行。 ContinueWith 委托是在taskCompletionSource.Task 完成后稍后执行的唯一代码。因此,要复制此行为,您需要将 ContinueWith 委托移动到方法的 end,这样所有同步代码都会像以前一样首先执行:

    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;
    }
    

    一旦您使用了async/await,您就可以通过使用using 声明进一步简化:

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-18
      • 2019-06-12
      • 2013-06-04
      • 2021-10-19
      • 2021-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      相关资源
      最近更新 更多