微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

永远不会从 Task.WaitAll 回来

如何解决永远不会从 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;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。