运行 使用 Task.Run() 的同步方法是否使其异步
Does running a synchronous method using Task.Run() make it asynchronous
让我们考虑一个 class(这不是我在我的应用程序中使用的 class 或代码,只是想通过这个例子来学习)
class Person
{
public int Id {get; set;}
public string Name {get; set;}
public int DeptId {get; set;}
public string Department {get; set;}
}
现在假设我从我的数据库中获得了上述 class 的对象列表。如果体积很大,我会想要一个部门 ID 和部门名称的字典。 Dictionary.
形式的东西
我在class里面有一个方法如下:
class Processing
{
private Task<Dictionary<int,string>> MapDepartments(List<Person> people) => Task.Run(()=> people.GroupBy(p=>p.DeptId).ToDictionary(group=> group.Key, group=>group.First().Department;
}
我的 class
中有一个单独的方法
class Processing
{
.
.
.
Task DoStuff()
{
.
.
.
//code execution to get data from the db
var departmentDictTask = MapDepartments(people);
.
.
.//some other code being executed, I don't need the department dictionary yet
.
.
var dictionaryData = await departmentDictTask.ConfigureAwait(false);
}
}
我的问题是:
- 这是我编写的用于从我的列表中创建字典的方法,它 运行 是异步的吗?
- 我认为是的,因为在调试时,我看到它处于“运行”状态一段时间,而我的其他代码是 运行ning。虽然我不确定是否确实如此。
- 这与将我的字典逻辑放在异步方法中有什么区别?
- 无论我实现了什么,这是否有点类似于拥有 .ToDictionaryAsync() 方法?
Here the method I've written to create a dictionary out of my List, does it run asynchronously?
可能更准确地说运行s 并列。创建一个单独的线程来产生结果。如果 people
没有以 thread-safe 的方式使用(例如,它是您要添加到其他线程中的列表),那么您最终可能会遇到混乱的竞争条件。
当人们谈论“异步”代码时,他们可能指的是两件事。
- 以不阻塞线程的方式模拟固有异步操作的代码,如磁盘或网络 I/O。
- 更广泛地说,可以独立于当前操作线程完成的任何类型的操作。
您所做的符合第二个定义,但不符合第一个。如果 people
由数据库 round-trip 支持,您的代码在该调用完成时仍会阻塞一个线程:它只会阻塞与调用 MapDepartments
.[= 的线程不同的线程。 26=]
What's the difference between this and putting my dictionary logic in an asynchronous method?
由于您是从 in-memory 列表中提取数据,并且您的所有操作都是 CPU-bound(不是真正的异步操作),因此将您的逻辑放在 async
方法,因为该方法对 await
没有任何意义。即使该方法会说它是 async
,它也会 运行 同步 在返回任务之前完成。
假设创建该字典确实需要足够的时间使其变得有价值 multi-threading,并且假设您在 await
任务之前没有修改基础列表,那么您当前的方法更好。
Whatever I've implemented is this somewhat similar to having a .ToDictionaryAsync() method?
我的意思是,我猜你可以写一个 ToDictionaryAsync
方法,它只在一个单独的线程上执行 ToDictionary
,但这确实不符合 Async
的精神。
当像 Entity Framework 这样的库提供 ToDictionaryAsync()
方法时,那是因为他们知道将有一个实际的数据库调用实际上是异步的,并且他们知道如何在non-blocking 方式而不调用 ToDictionary()
。对于这种情况,我会保留 ToDictionaryAsync
。
让我们考虑一个 class(这不是我在我的应用程序中使用的 class 或代码,只是想通过这个例子来学习)
class Person
{
public int Id {get; set;}
public string Name {get; set;}
public int DeptId {get; set;}
public string Department {get; set;}
}
现在假设我从我的数据库中获得了上述 class 的对象列表。如果体积很大,我会想要一个部门 ID 和部门名称的字典。 Dictionary
我在class里面有一个方法如下:
class Processing
{
private Task<Dictionary<int,string>> MapDepartments(List<Person> people) => Task.Run(()=> people.GroupBy(p=>p.DeptId).ToDictionary(group=> group.Key, group=>group.First().Department;
}
我的 class
中有一个单独的方法class Processing
{
.
.
.
Task DoStuff()
{
.
.
.
//code execution to get data from the db
var departmentDictTask = MapDepartments(people);
.
.
.//some other code being executed, I don't need the department dictionary yet
.
.
var dictionaryData = await departmentDictTask.ConfigureAwait(false);
}
}
我的问题是:
- 这是我编写的用于从我的列表中创建字典的方法,它 运行 是异步的吗?
- 我认为是的,因为在调试时,我看到它处于“运行”状态一段时间,而我的其他代码是 运行ning。虽然我不确定是否确实如此。
- 这与将我的字典逻辑放在异步方法中有什么区别?
- 无论我实现了什么,这是否有点类似于拥有 .ToDictionaryAsync() 方法?
Here the method I've written to create a dictionary out of my List, does it run asynchronously?
可能更准确地说运行s 并列。创建一个单独的线程来产生结果。如果 people
没有以 thread-safe 的方式使用(例如,它是您要添加到其他线程中的列表),那么您最终可能会遇到混乱的竞争条件。
当人们谈论“异步”代码时,他们可能指的是两件事。
- 以不阻塞线程的方式模拟固有异步操作的代码,如磁盘或网络 I/O。
- 更广泛地说,可以独立于当前操作线程完成的任何类型的操作。
您所做的符合第二个定义,但不符合第一个。如果 people
由数据库 round-trip 支持,您的代码在该调用完成时仍会阻塞一个线程:它只会阻塞与调用 MapDepartments
.[= 的线程不同的线程。 26=]
What's the difference between this and putting my dictionary logic in an asynchronous method?
由于您是从 in-memory 列表中提取数据,并且您的所有操作都是 CPU-bound(不是真正的异步操作),因此将您的逻辑放在 async
方法,因为该方法对 await
没有任何意义。即使该方法会说它是 async
,它也会 运行 同步 在返回任务之前完成。
假设创建该字典确实需要足够的时间使其变得有价值 multi-threading,并且假设您在 await
任务之前没有修改基础列表,那么您当前的方法更好。
Whatever I've implemented is this somewhat similar to having a .ToDictionaryAsync() method?
我的意思是,我猜你可以写一个 ToDictionaryAsync
方法,它只在一个单独的线程上执行 ToDictionary
,但这确实不符合 Async
的精神。
当像 Entity Framework 这样的库提供 ToDictionaryAsync()
方法时,那是因为他们知道将有一个实际的数据库调用实际上是异步的,并且他们知道如何在non-blocking 方式而不调用 ToDictionary()
。对于这种情况,我会保留 ToDictionaryAsync
。