我有这样的疑问。例如,我使用mvvm模式动态创建自定义userControl。所以我发出了一个创建userControl的命令。所以创作看起来像
private async Task<bool> OnAddUserControl1(List<ALV_VM_ADWERT> control)
{
try
{
_cancellationTokenSource = new CancellationTokenSource();
var userControl = _userControlsContainer.CreateUserControl1(control);
var task1 = Task.Factory.StartNew(() =>
{
userControl.ViewModel.InOperationEvent += OnUsercontrolInOperationChanged;
userControl.ViewModel.ValueTypeChangedEvent += OnValueTypeChanged;
userControl.ViewModel.SetExpandableName += OnSetExpandableName;
}, _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
var task2 = Task.Factory.StartNew(() => FinalCreatingStep(userControl, control[0].RAUMNAME.Trim()), _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
await Task.WhenAll(task1, task2);
return true;
}
catch (Exception)
{
return false;
}
}
我的问题是 - 是否可以创建子任务,或者更好地拥有没有子任务的代码?如果答案是肯定的,那么我应该让所有方法都异步吗?如果没有,我不应该做什么方法异步?
答案 0 :(得分:4)
那些事件订阅真的需要异步吗?您可能正在努力使用异步代码。
用户控件构造函数通常是最耗时的部分,必须在UI线程上完成。通常只有在调用某种形式的IO或处理时才需要异步操作;
简而言之,异步任务在这里可能有些过分。
答案 1 :(得分:3)
是否可以创建子任务,或者最好是没有子任务的代码?
这取决于您的要求。如果您的UI将被阻止(冻结)很长时间,您必须创建一个子任务,否则不会!
如果答案是肯定的,那么我应该让所有方法都异步吗?如果没有,我不应该采用什么方法异步?
这也取决于您的要求和您的.Net版本。如果您使用的是.NET 4.5,最简单的方法是使用Async等待。如果您使用的是.Net 3.5而不仅仅是使用Task。如果.Net 2使用BackgorundWorker,则使用Thread类。只有异步方法必须得到单词async。您不必更改它们的其他方法。换句话说,只有阻止UI的方法。
答案 2 :(得分:2)
您当前的代码没有任何意义。
UI应用程序中async
代码的要点是响应性 - 即,将长时间运行的操作移出UI线程。正如@Gusdor指出的那样,async
的大多数用例都是基于I / O(或基于事件的)操作,您不希望阻止UI线程等待某些结果。另一个用例是当你有一些CPU绑定的工作要做,但你不想绑定UI线程;在这种情况下,您可以使用Task.Run
。
但在您的代码中,您使用StartNew
调用TaskScheduler.FromCurrentSynchronizationContext
,这意味着您的“子”任务将在UI线程上执行。所以你的OnAddUserControl1
只是启动将在同一个线程上运行并异步等待它们完成的任务。这是一种非常复杂的无所事事的方式。
虽然我们讨论的是StartNew
,但还存在许多其他问题:
CancellationToken
而没有在委托中观察它。AttachedToParent
对于await
兼容的任务不正确。TaskScheduler
,它将在UI线程上运行委托。如果您需要使用后台(线程池)任务,则应使用Task.Run
instead of Task.Factory.StartNew
;我在博客上详细介绍了。
因此,对于此示例,使用async
或await
毫无意义。
开始使用async
的最佳方法是首先识别I / O绑定(或事件驱动)部分(例如,HTTP请求,数据库调用),使它们成为async
,以及然后按照调用堆栈的方式工作。