调用异步方法和Task.Run异步方法之间的区别

nim*_*tra 6 c# xaml asynchronous task-parallel-library async-await

我的视图模型中有一个方法

private async void SyncData(SyncMessage syncMessage)
{
    if (syncMessage.State == SyncState.SyncContacts)
    {
        this.SyncContacts(); 
    }
}

private async Task SyncContacts()
{
    foreach(var contact in this.AllContacts)
    {
       // do synchronous data analysis
    }

    // ...

    // AddContacts is an async method
    CloudInstance.AddContacts(contactsToUpload);
}
Run Code Online (Sandbox Code Playgroud)

当我SyncData从UI命令调用时,我正在同步大量数据UI冻结.但是当我SyncContacts用这种方法打电话时

private void SyncData(SyncMessage syncMessage)
{
    if (syncMessage.State == SyncState.SyncContacts)
    {
        Task.Run(() => this.SyncContacts()); 
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都好.它们不应该是一样的吗?我当时认为不使用await来调用异步方法会创建一个新线程.

Yuv*_*kov 9

它们不应该是一样的吗?我当时认为不使用await来调用异步方法会创建一个新线程.

不,async不会为它的方法调用神奇地分配新线程.async-await主要是利用自然异步API,例如对数据库的网络调用或远程Web服务.

使用时Task.Run,您明确使用线程池线程来执行您的委托.如果使用async关键字标记方法,但在await内部不标记任何内容,则它将同步执行.

我不确定你的SyncContacts()方法实际上做了什么(因为你没有提供它的实现),但是单独标记它将async不会获得任何东西.

编辑:

现在你已经添加了实现,我看到两件事:

  1. 我不确定您的同步数据分析是如何CPU密集的,但它可能足以让UI无法响应.
  2. 您不是在等待异步操作.它需要看起来像这样:

    private async Task SyncDataAsync(SyncMessage syncMessage)
    {
        if (syncMessage.State == SyncState.SyncContacts)
        {
            await this.SyncContactsAsync(); 
        }
    }
    
    private Task SyncContactsAsync()
    {
        foreach(var contact in this.AllContacts)
        {
           // do synchronous data analysis
        }
    
        // ...
    
        // AddContacts is an async method
        return CloudInstance.AddContactsAsync(contactsToUpload);
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • @Gusdor [`Task.Run`](http://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,89fc01f3bb88eed9)默认为[`TaskScheduler.Default`](http:// referencesource) .microsoft.com/#mscorlib/system/threading/Tasks/TaskScheduler.cs,d4a38cb3e3085518),这是线程池任务调度程序. (4认同)