Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# wpf应用中的异步/等待方法_C#_Wpf_Asynchronous - Fatal编程技术网

C# wpf应用中的异步/等待方法

C# wpf应用中的异步/等待方法,c#,wpf,asynchronous,C#,Wpf,Asynchronous,我有这样的问题。例如,我使用mvvm模式动态创建自定义userControl。所以我发送了一个命令来创建一个userControl。所以创造看起来像 private async Task<bool> OnAddUserControl1(List<ALV_VM_ADWERT> control) { try { _cancellationTokenSource = new CancellationTokenSource(); v

我有这样的问题。例如,我使用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;
    }                
}
ADDUSERCONTROL1(列表控件)上的专用异步任务 { 尝试 { _cancellationTokenSource=新的cancellationTokenSource(); var userControl=\u userControlsContainer.CreateUserControl1(控件); 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()); 等待任务。WhenAll(任务1,任务2); 返回true; } 捕获(例外) { 返回false; } }
我的问题是-创建子任务有意义吗,还是让代码没有子任务更好?如果答案是肯定的,那么我应该使所有方法都异步吗?如果不是,我不应该使哪些方法异步?

这些事件订阅真的需要异步吗?您可能过于努力地使用异步代码

用户控件构造函数通常是最耗时的部分,必须在UI线程上完成。异步操作通常仅在涉及某种形式的IO或处理时才需要

  • 读取文件
  • 写文件
  • 处理大型数据集
  • 跨越进程边界与服务器或连接设备通话
简言之,异步任务在这里可能有点过头了。

创建子任务有意义吗,还是让代码没有子任务更好?

这取决于您的要求。如果您的UI将被长时间阻止(冻结),则必须创建子任务,否则不能

如果答案是肯定的,那么我应该使所有方法都异步吗?如果不是,我应该使哪些方法不异步?


这也取决于您的需求和.Net版本。如果您使用的是.NET4.5,那么使用AsyncAwait是最简单的方法。如果您使用的是.NET3.5,那么就不要只使用Task。如果.Net 2使用BackgorundWorker,则使用线程类。只有异步方法必须使用async这个词。其他方法您不必更改它们。换句话说,只有阻止UI的方法。

您当前的代码没有任何意义

UI应用程序中的
async
代码的要点是响应性,即将长时间运行的操作移出UI线程。正如@Gusdor所指出的,
async
的大多数用例都是基于I/O(或基于事件)的操作,您不希望为了等待结果而阻塞UI线程。另一个用例是当您有一些CPU限制的工作要做,但您不想占用UI线程;在这种情况下,可以使用
Task.Run

但是在您的代码中,您正在使用任务调度器调用
StartNew
。FromCurrentSynchronizationContext,这意味着您的“子”任务将在UI线程上执行。因此,您的
OnAddUserControl1
只是启动将在同一线程上运行的任务,并异步等待它们完成。这是一种非常复杂的无所事事的方式

当我们讨论
StartNew
时,还有一些其他问题:

  • 代码正在传递一个
    CancellationToken
    ,但从未在委托中观察到它
  • 代码指定了
    AttachedToParent
    ,这对于
    wait
    兼容的任务是不正确的
  • 如上所述,代码正在传递一个
    TaskScheduler
    ,它将在UI线程上运行委托
  • 如果需要使用后台(线程池)任务,则应使用;我会在我的博客上详细介绍

    因此,对于本例,使用
    async
    wait
    根本没有意义


    开始使用
    async
    的最佳方法是首先识别I/O绑定(或事件驱动)部分(例如HTTP请求、数据库调用),使它们
    async
    ,然后逐步向上扩展调用堆栈。

    可能是,但我正在使用数据库中的信息创建userControl,一开始,它可以是一百个或更多个控件。那么,在没有子任务的情况下使用这种方法会更好吗?对吗?@Sasha我的建议是,为您要创建的每个控件(这对于让调度器正常工作很重要)ping掉一个任务以检索数据并开始调用调度器。感谢您的帮助。