永远不会从 Task.WaitAll 回来

问题描述

仍在加快 Xamarin 和 C# 的速度。

我有一些代码,例如:

        List<Task<int>> taskList = new List<Task<int>>();
        ConfigEntry siteId = new ConfigEntry
        {
            ConfigKey = KEY_SITE_ID,ConfigValue = siteInfo.siteId
        };
        taskList.Add(ConfigDatabase.SaveConfigAsync(siteId));

        ConfigEntry productId = new ConfigEntry
        {
            ConfigKey = KEY_PRODUCT_ID1,ConfigValue = siteInfo.products[0].productId.ToString()
        };
        taskList.Add(ConfigDatabase.SaveConfigAsync(productId));

总共有九个被添加taskList。这些中的每一个都将内容插入 sqlITE。这是正在运行的代码

    public async Task<int> SaveConfigAsync(ConfigEntry entry)
    {
        if (entry.ConfigKey == null)
        {
            throw new Square1Exception("Config entry key not defined:" + entry);
        }
        else
        {
            try
            {
                ConfigEntry existing = await GetConfigAsync(entry.ConfigKey);
                if (existing == null)
                {
                    return await _database.InsertAsync(entry);
                }
                else
                {
                    existing.UpdateFrom(entry);
                    return await _database.UpdateAsync(entry);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error while saving value:" + entry.ConfigKey);
                throw ex;
            }
        }
    }

所以在这个任务列表的构建结束时,我有以下一行:

        Task.WaitAll(taskList.ToArray());

我希望等到所有添加完成后再退出。相反,它永远不会从这里回来。它只是挂起我的整个应用程序。日志中也没有看到任何内容。它(可能)在创建时启动任务还是等到像 WaitAll 这样的东西?

如果我用一个等待和单线程替换每个添加,它工作正常。也许在数据库或磁盘上阻塞?

想法?

解决方法

You shouldn't block on asynchronous code

最好的解决方法是将 Task.WaitAll(taskList.ToArray()); 更改为 await Task.WhenAll(taskList);

如果您必须阻塞,那么您可以使用 Task.Run 将工作推送到后台线程,例如:

taskList.Add(Task.Run(() => ConfigDatabase.SaveConfigAsync(siteId)));
...
taskList.Add(Task.Run(() => ConfigDatabase.SaveConfigAsync(productId)));

但是那样你就会在 Task.WaitAll 处阻塞你的 UI 线程,所以我不推荐这种方法。使用 await Task.WhenAll 更好。

,

您在执行 Task.WhenAll(Tasks) 时缺少 await。 尝试以下解决方案:

ConfigEntry siteId = new ConfigEntry
{
    ConfigKey = KEY_SITE_ID,ConfigValue = siteInfo.siteId
};
ConfigEntry productId = new ConfigEntry
{
    ConfigKey = KEY_PRODUCT_ID1,ConfigValue = siteInfo.products[0].productId.ToString()
};

var insertResultFirstTask = ConfigDatabase.SaveConfigAsync(siteId)
var insertResultSecondTask = ConfigDatabase.SaveConfigAsync(productId)

IEnumerable<Task> tasks = new List<Task>() {
    insertResultFirstTask,insertResultSecondTask
};

await Task.WhenAll(tasks);

var insertResultFirst = insertResultFirstTask.Result;
var insertResultSecond = insertResultSecondTask.Result;