C#异步函数-Wait是否立即在新线程上启动任务?

C#异步函数-Wait是否立即在新线程上启动任务?,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,我正在为异步操作重构一些C#代码,但恐怕我没有深入了解C#wait指令的情况。我有一个方法,该方法可能会进行一些冗长的处理,并且需要连续运行200次: public LanDeviceInfo GetLanDBData(LanDeviceInfo device) 我创建了一个使用它的异步版本: public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device) { var deviceInfo

我正在为异步操作重构一些C#代码,但恐怕我没有深入了解C#wait指令的情况。我有一个方法,该方法可能会进行一些冗长的处理,并且需要连续运行200次:

public LanDeviceInfo GetLanDBData(LanDeviceInfo device) 
我创建了一个使用它的异步版本:

public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
{
    var deviceInfo = await Task.Run(() => GetLanDBData(device));
    return deviceInfo;
}
所有这些都可以正常工作,函数以异步方式调用,我的UI不会被阻塞

现在,我不明白的是,为什么按如下方式定义GetLanDBDataAsync函数可以很好地编译,但不起作用并阻塞UI线程:

public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
{
    return GetLanDBData(device);
}
公共异步任务GetLanDBDataAsync(LanDeviceInfo设备)
{
返回GetLanDBData(设备);
}
据我所知,这也应该有效。使用async修饰符和Task return类型定义此函数将使编译器自动生成一个任务,该任务将在调用
GetLanDBDataAsync()
时返回。然后从
GenerateCommissionFile()
调用
await GetLanDBDataAsync()
,将自动使其在新线程中运行,而不会阻塞UI。为什么我必须手动创建一个任务来运行
GetLanDBData()
并在
GetLanDBDataAsync()
中等待它,而在UI线程上运行的
GenerateCommissioningFile()
已经在等待异步函数了?我觉得我真的错过了一些东西;)

谢谢

对于此功能:

public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
{
    return GetLanDBData(device);
}
非常粗暴地意味着-

  • GetLanDBDataAsync
    方法中创建一个表示整个操作的任务。让我们把它命名为
    taskResult

  • 队列
    GetLanDBData
    将在线程池上执行(因为
    Task.Run
    的文档说明了这一点,而不仅仅是因为“它是一个任务”)。从
    Task.Run返回的任务表示此挂起的操作

  • 现在,如果从
    task.Run
    返回的任务尚未完成(它没有),则将
    taskResult
    (表示整个操作)返回给调用者

  • 当一段时间后任务从
    task.Run
    返回时,我们将执行剩余的代码。在本例中,
    Task.Run
    的结果只是转发到我们的
    taskResult
    ,因为其余的代码只是
    返回设备信息

  • 对于此功能:

    public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
    {
        return GetLanDBData(device);
    }
    
    非常粗暴地意味着-

  • GetLanDBDataAsync
    方法中创建一个表示整个操作的任务。让我们把它命名为
    taskResult

  • 队列
    GetLanDBData
    将在线程池上执行(因为
    Task.Run
    的文档说明了这一点,而不仅仅是因为“它是一个任务”)。从
    Task.Run返回的任务表示此挂起的操作

  • 现在,如果从
    task.Run
    返回的任务尚未完成(它没有),则将
    taskResult
    (表示整个操作)返回给调用者

  • 当一段时间后任务从
    task.Run
    返回时,我们将执行剩余的代码。在本例中,
    Task.Run
    的结果只是转发到我们的
    taskResult
    ,因为其余的代码只是
    返回设备信息


  • 这不是一个正确的答案,但在最后一个代码片段中,您甚至不应该使用
    async
    async
    是允许在函数内部使用
    wait
    。最后一个
    GetLanDBDataAsync
    阻塞UI线程,因为函数同步调用
    GetLanDBData
    ,因此,它被标记为“异步”与否,甚至它返回一个任务都没有区别。
    wait
    等待一个已经执行的操作。
    async
    wait
    都不启动该操作。但是,您的代码不使用异步执行,而是在单独的线程中执行数据库代码。并导致一个bug,因为不能等待
    async void
    。使用异步操作而不是
    任务。对不返回结果的异步操作运行
    异步任务
    GetLanDBData
    做什么?这是最重要的代码。如果您连接到数据库,您可以用
    OpenAsync
    替换
    Open
    ExecuteReader
    替换
    ExecuteReaderAsync
    等,并获得真正的异步执行建议阅读:这不是正确的答案,但在最后一个代码片段中,您甚至不应该使用
    async
    async
    允许在函数内部使用
    wait
    。最后一个
    GetLanDBDataAsync
    阻塞UI线程,因为函数同步调用
    GetLanDBData
    ,因此标记为“async”与否没有区别,甚至返回任务。
    await
    等待已经执行的操作。
    async
    wait
    都不启动该操作。但是,您的代码不使用异步执行,而是在单独的线程中执行数据库代码。并导致一个bug,因为不能等待
    async void
    。使用异步操作而不是
    任务。对不返回结果的异步操作运行
    异步任务
    GetLanDBData
    做什么?这是最重要的代码。如果你连接到一个数据库,你可以用
    OpenAsync
    替换
    Open
    ExecuteReader
    替换
    ExecuteReaderAsync
    等,并获得真正的异步执行推荐阅读:谢谢,我想我开始理解了。所以一个任务并不总是产生一个新线程,它只是异步运行代码的一种方式,并且能够在代码完成后使用“wait”执行回调?在这种情况下,编译器为GetLanDBDataAsync(在
    public Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
    {
        var result = GetLanDBData(device);
        return Task.FromResult(result);
    }
    
    public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
    {
        var deviceInfo = await Task.Run(() => GetLanDBData(device));
        return deviceInfo;
    }