永远不会从 Task.WaitAll 回来
Never coming back from 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));
总共有 9 个被添加到 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 之类的东西?
如果我用 await 和单线程替换每个添加,它们就可以正常工作。可能阻塞在数据库或磁盘上?
想法?
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(任务)时缺少 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;
仍在加快 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));
总共有 9 个被添加到 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 之类的东西?
如果我用 await 和单线程替换每个添加,它们就可以正常工作。可能阻塞在数据库或磁盘上?
想法?
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(任务)时缺少 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;