Call asynchronous method in constructor
1 using System; 2 using System.ComponentModel; 3 using System.Threading.Tasks; 4 public sealed class NotifyTaskCompletion<TResult> : INotifyPropertyChanged 5 { 6 public NotifyTaskCompletion(Task<TResult> task) 7 { 8 Task = task; 9 if (!task.IsCompleted) 10 { 11 var _ = WatchTaskAsync(task); 12 } 13 } 14 private async Task WatchTaskAsync(Task task) 15 { 16 try 17 { 18 await task; 19 } 20 catch 21 { 22 } 23 var propertyChanged = PropertyChanged; 24 if (propertyChanged == null) 25 return; 26 propertyChanged(this, new PropertyChangedEventArgs("Status")); 27 propertyChanged(this, new PropertyChangedEventArgs("IsCompleted")); 28 propertyChanged(this, new PropertyChangedEventArgs("IsNotCompleted")); 29 if (task.IsCanceled) 30 { 31 propertyChanged(this, new PropertyChangedEventArgs("IsCanceled")); 32 } 33 else if (task.IsFaulted) 34 { 35 propertyChanged(this, new PropertyChangedEventArgs("IsFaulted")); 36 propertyChanged(this, new PropertyChangedEventArgs("Exception")); 37 propertyChanged(this, 38 new PropertyChangedEventArgs("InnerException")); 39 propertyChanged(this, new PropertyChangedEventArgs("ErrorMessage")); 40 } 41 else 42 { 43 propertyChanged(this, 44 new PropertyChangedEventArgs("IsSuccessfullyCompleted")); 45 propertyChanged(this, new PropertyChangedEventArgs("Result")); 46 } 47 } 48 public Task<TResult> Task { get; private set; } 49 public TResult Result { get { return (Task.Status == TaskStatus.RanToCompletion) ? 50 Task.Result : default(TResult); } } 51 public TaskStatus Status { get { return Task.Status; } } 52 public bool IsCompleted { get { return Task.IsCompleted; } } 53 public bool IsNotCompleted { get { return !Task.IsCompleted; } } 54 public bool IsSuccessfullyCompleted { get { return Task.Status == 55 TaskStatus.RanToCompletion; } } 56 public bool IsCanceled { get { return Task.IsCanceled; } } 57 public bool IsFaulted { get { return Task.IsFaulted; } } 58 public AggregateException Exception { get { return Task.Exception; } } 59 public Exception InnerException { get { return (Exception == null) ? 60 null : Exception.InnerException; } } 61 public string ErrorMessage { get { return (InnerException == null) ? 62 null : InnerException.Message; } } 63 public event PropertyChangedEventHandler PropertyChanged; 64 }
An updated ViewModel using NotifyTaskCompletion<T> would look like this:
1 public class MainViewModel 2 { 3 public MainViewModel() 4 { 5 UrlByteCount = new NotifyTaskCompletion<int>( 6 MyStaticService.CountBytesInUrlAsync("http://www.example.com")); 7 } 8 public NotifyTaskCompletion<int> UrlByteCount { get; private set; } 9 }
1 <Window x:Class="MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 4 <Window.Resources> 5 <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> 6 </Window.Resources> 7 <Grid> 8 <!-- Busy indicator --> 9 <Label Content="Loading..." Visibility="{Binding UrlByteCount.IsNotCompleted, 10 Converter={StaticResource BooleanToVisibilityConverter}}"/> 11 <!-- Results --> 12 <Label Content="{Binding UrlByteCount.Result}" Visibility="{Binding 13 UrlByteCount.IsSuccessfullyCompleted, 14 Converter={StaticResource BooleanToVisibilityConverter}}"/> 15 <!-- Error details --> 16 <Label Content="{Binding UrlByteCount.ErrorMessage}" Background="Red" 17 Visibility="{Binding UrlByteCount.IsFaulted, 18 Converter={StaticResource BooleanToVisibilityConverter}}"/> 19 </Grid> 20 </Window>
From: https://msdn.microsoft.com/en-us/magazine/dn605875.aspx
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构