【发布时间】:2020-03-12 22:10:49
【问题描述】:
列表中有几个对象。每分钟,对于他们每个人,我都必须下载api信息并将接收到的数据保存到数据库中。
列表中的对象相互独立。每个对象的方法都可以单独调用。根据 api 的响应时间,单个方法的总执行时间通常在 ~0.5 到 5 秒之间。
按照stackoverflow上其他线程的建议,我创建了以下代码:
private async void DownloadAndSaveDataForMyObjects(object state)
{
try
{
await Task.Run(() => Parallel.ForEach(MyObjectsList, ServiceSingleObjectMethod));
}
}
private void ServiceSingleObjectMethod(RehDeviceSmsRequest myObjectFromList)
{
var apiInfo = GetInfoFromApi(myObjectFromList);
SaveInfoToDatabase(myObjectFromList);
}
在我看来,代码是异步的。但是……我有些怀疑。记录器通知我在应用程序运行期间执行的操作。对象的方法调用之间的间隔非常大。请看这个:
[13:32:46 DBG][MyService]->MyMethod => Update object id: 54
[13:32:47 DBG][MyService]->MyMethod => Update object id: 9
[13:32:50 DBG][MyService]->MyMethod => Update object id: 47
[13:32:51 DBG][MyService]->MyMethod => Update object id: 21
[13:32:51 DBG][MyService]->MyMethod => Update object id: 53
[13:32:53 DBG][MyService]->MyMethod => Update object id: 37
[13:32:55 DBG][MyService]->MyMethod => Update object id: 62
[13:32:55 DBG][MyService]->MyMethod => Update object id: 63
[13:32:56 DBG][MyService]->MyMethod => Update object id: 64
[13:32:56 DBG][MyService]->MyMethod => Update object id: 55
[13:32:56 DBG][MyService]->MyMethod => Update object id: 36
[13:32:56 DBG][MyService]->MyMethod => Update object id: 30
[13:32:56 DBG][MyService]->MyMethod => Update object id: 46
[13:32:56 DBG][MyService]->MyMethod => Update object id: 26
[13:32:56 DBG][MyService]->MyMethod => Update object id: 56
[13:33:00 DBG][MyService]->MyMethod => Update object id: 29
[13:33:00 DBG][MyService]->MyMethod => Update object id: 57
[13:33:00 DBG][MyService]->MyMethod => Update object id: 42
[13:33:01 DBG][MyService]->MyMethod => Update object id: 38
[13:33:01 DBG][MyService]->MyMethod => Update object id: 32
[13:33:01 DBG][MyService]->MyMethod => Update object id: 48
[13:33:01 DBG][MyService]->MyMethod => Update object id: 40
[13:33:01 DBG][MyService]->MyMethod => Update object id: 31
[13:33:01 DBG][MyService]->MyMethod => Update object id: 49
[13:33:02 DBG][MyService]->MyMethod => Update object id: 58
[13:33:02 DBG][MyService]->MyMethod => Update object id: 9
[13:33:02 DBG][MyService]->MyMethod => Update object id: 33
[13:33:02 DBG][MyService]->MyMethod => Update object id: 41
[13:33:04 DBG][MyService]->MyMethod => Update object id: 50
[13:33:04 DBG][MyService]->MyMethod => Update object id: 34
[13:33:06 DBG][MyService]->MyMethod => Update object id: 17
[13:33:06 DBG][MyService]->MyMethod => Update object id: 59
[13:33:07 DBG][MyService]->MyMethod => Update object id: 45
[13:33:08 DBG][MyService]->MyMethod => Update object id: 61
[13:33:08 DBG][MyService]->MyMethod => Update object id: 54
[13:33:08 DBG][MyService]->MyMethod => Update object id: 43
[13:33:08 DBG][MyService]->MyMethod => Update object id: 51
[13:33:08 DBG][MyService]->MyMethod => Update object id: 52
处理后续对象的间隔相当大。我认为我的异步代码会使每个对象的方法同时被调用(或者非常非常相似)......
如何确保我的代码是异步的并且可以正常工作? 你能确认我正确地为每个对象调用任务吗?
【问题讨论】:
-
您是否尝试记录每个并行任务的线程 ID (
Thread.CurrentThread.ManagedThreadId)? -
你使用的是哪个
SynchronizationContext? -
我看到六个日志条目的时间为“13:33:01”....我不知道这是什么意思,但它似乎符合“每个对象的方法同时被调用”的标准。
-
请澄清您是否在问题中使用“异步”一词作为“并行运行”。请注意,
async和Parallel.ForEach都没有保证 all 操作将并行运行(ForEach实际上几乎可以保证,因为它使用自己的内部策略并行运行迭代) -
正如迈克尔兰德尔在他的出色回答中提到的那样,Parallel.ForEach 并不是您真正想要的。如果您真的想为每个项目启动一个线程,请创建一个
List<Task>,循环您的MyObjectList并将Task.Run任务添加到循环内的List。然后你可以await Task.WhenAll(taskList);你会注意到你的输出有所不同。
标签: c# asynchronous parallel.foreach