C#异步函数-Wait是否立即在新线程上启动任务?
我正在为异步操作重构一些C#代码,但恐怕我没有深入了解C#wait指令的情况。我有一个方法,该方法可能会进行一些冗长的处理,并且需要连续运行200次: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
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;
}