首页 > 解决方案 > 使用延续任务的链式任务

问题描述

我正在尝试链接任务,因此一旦完成下一个任务就会启动,但 UI 不会更新。我做了一门反应课程,其中一课是您根据应用程序中的状态更改更新 UI,这就是我想要复制的内容。更改应用程序的状态(基本上我将运行运行返回 bool 进行验证的方法),然后相应地更新 UI,我也在使用绑定,但由于某种原因它没有按预期运行,我没有不知道我是否错误地遵循了文档。async Task<T>我可以更改或修复什么来完成这项工作,在一种方法中使用多个任务实际上是否正确

public async Task<string> Connect_To_Ip()
{
    await Task.Run(() =>
    {
        details.State = "Connection To IP 127.0.01.258.....";
        Task.Delay(5000).Wait();
        }).ContinueWith(result => new Task(async () =>
        {
           await Task.Run(() =>
           {
               if (result.Status == TaskStatus.RanToCompletion)
               {
                  details.State = "Validating Card Number......";
                }                    
           });  
              
        }), TaskContinuationOptions.OnlyOnRanToCompletion);

     return details.State;
}     

我如何调用原始任务

Task connect = Connect_To_Ip();
await connect;

标签: c#wpfasync-await

解决方案


当你使用时await,你不需要Task.ContinueWith. 等待的操作之后的一切都是延续。由于要在后台线程上进行验证,因此必须将更改发布回 UI 线程以更新 UI 元素,否则会产生跨线程异常。
这是因为 UI 元素不能从后台线程更新,除非更新是通过INotifyPropertyChanged数据绑定发生的。
一种方法是使用Dispatcher调用 UI 线程上的 UI 操作或使用Progress<T>类,这将始终在 UI 线程上执行注册的回调。

您的固定和简化代码可能类似于以下示例:

public async Task ValidateAsync()
{
  // Register the callback that updates the UI with the 'progressReporter'.
  // Progress<T> must be instantiated on the UI thread it is associated with
  var progressReporter = new Progress<string>(message => details.State = message);

  // Execute the operation on a background thread
  await Task.Run(() => ConnectToIp(progressReporter));

  // Continuation starts here, after await
}

public async Task ConnectToIp(IProgress<string> progressReporter)
{
  progressReporter.Report("Connection To IP 127.0.01.258.....");

  await Task.Delay(TimeSpan.FromSeconds(5));

  // Continuation starts here, after await

  progressReporter.Report("Validating Card Number......");
}

建议尽可能使用异步 API,而不是使用后台线程。例如,要在不阻塞 UI 的情况下连接到服务器,您可以使用

HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");

许多 IO 类提供异步 API。

此外,我建议看一下INotifyDataErrorInfo界面。这是实现属性验证的推荐方式,并允许以非常简单的方式提供 UI 错误反馈。


推荐阅读