c# - 如何防止一种异步方法垄断另一种方法?
问题描述
在我的 UWP 应用程序中,我有一个异步方法(事件处理程序),它调用另一个异步方法,该方法尝试将记录插入数据库。
我在插入尝试中遇到了异常,并试图解释为什么会发生这种情况。所以我在 InsertMapRecord() 方法的第一个“使用”行上放了一个断点:
using (SqliteConnection conn = new SqliteConnection(connStr))
当我到达那个断点时,我按了 F10,但不是将我带到 Insert 方法中的下一行,而是将我带到 btnCre8NewMap_Click() 中的这一行,事件处理程序(您会认为它已经被击中,因为已到达上一行):
InsertMapRecord(mapName, mapNotes, defaultZoomLevel);
然后我按了 F11,试图返回 InsertMapRecord() 方法,但我最终在 App.gics 中,在这一行:
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
#endif
...突出显示“ global::System.Diagnostics.Debugger.Break() ”,然后显示以下异常消息:
完整的方法如下
private async void btnCre8NewMap_Click(object sender, RoutedEventArgs e)
{
try
{
string mapName = string.Empty;
string mapNotes = string.Empty;
int defaultZoomLevel = 1;
ClearLocations();
// Popul8 the cmbx
for (int i = 1; i < 20; i++)
{
cmbxCre8MapZoomLevels.Items.Add(i.ToString());
}
ContentDialogResult result = await cntDlgCre8Map.ShowAsync();
if (result == ContentDialogResult.Primary)
{
mapName = txtbxMapName.Text;
mapNotes = txtbxMapNotes.Text;
defaultZoomLevel = cmbxCre8MapZoomLevels.SelectedIndex + 1;
InsertMapRecord(mapName, mapNotes, defaultZoomLevel);
}
// else do nothing (don't save)
}
catch (Exception ex)
{
MessageDialog exceptionMsgDlg = new MessageDialog(ex.Message, "btnCre8NewMap_Click");
await exceptionMsgDlg.ShowAsync();
}
}
private async void InsertMapRecord(string mapName, string mapNotes, int preferredZoomLevel)
{
path = folder.Path;
connStr = string.Format(connStrBase, path);
try
{
using (SqliteConnection conn = new SqliteConnection(connStr))
{
String query = "INSERT INTO dbo.CartographerMain " +
"(MapName, MapNotes, PreferredZoomLevel) " +
"VALUES (@MapName, @MapNotes, @PreferredZoomLevel)";
using (SqliteCommand cmd = new SqliteCommand(query, conn))
{
cmd.Parameters.AddWithValue("@MapName", mapName);
cmd.Parameters.AddWithValue("@MapNotes", mapNotes);
cmd.Parameters.AddWithValue("@PreferredZoomLevel", preferredZoomLevel);
conn.Open();
int result = cmd.ExecuteNonQuery();
if (result < 0)
{
MessageDialog dialog = new MessageDialog("Error inserting data into CartographerMain");
await dialog.ShowAsync();
}
}
}
}
catch (SqliteException sqlex)
{
MessageDialog dialog = new MessageDialog(sqlex.Message, "InsertMapRecord");
await dialog.ShowAsync();
}
}
解决方案
该InsertMapRecord
方法应该返回一个Task
可以由调用者等待的。此外,当您打开与数据库的连接或执行查询时,它不应阻塞:
private async Task InsertMapRecord(string mapName, string mapNotes, int preferredZoomLevel)
{
path = folder.Path;
connStr = string.Format(connStrBase, path);
try
{
using (SqliteConnection conn = new SqliteConnection(connStr))
{
String query = "INSERT INTO dbo.CartographerMain " +
"(MapName, MapNotes, PreferredZoomLevel) " +
"VALUES (@MapName, @MapNotes, @PreferredZoomLevel)";
using (SqliteCommand cmd = new SqliteCommand(query, conn))
{
cmd.Parameters.AddWithValue("@MapName", mapName);
cmd.Parameters.AddWithValue("@MapNotes", mapNotes);
cmd.Parameters.AddWithValue("@PreferredZoomLevel", preferredZoomLevel);
await conn.OpenAsync();
int result = await cmd.ExecuteNonQueryAsync();
if (result < 0)
{
MessageDialog dialog = new MessageDialog("Error inserting data into CartographerMain");
await dialog.ShowAsync();
}
}
}
}
catch (SqliteException sqlex)
{
MessageDialog dialog = new MessageDialog(sqlex.Message, "InsertMapRecord");
await dialog.ShowAsync();
}
}
void
应避免使用异步方法(事件处理程序除外)。
在您的事件处理程序中,您应该等待该InsertMapRecord
方法和任何其他异步方法:
if (result == ContentDialogResult.Primary)
{
mapName = txtbxMapName.Text;
mapNotes = txtbxMapNotes.Text;
defaultZoomLevel = cmbxCre8MapZoomLevels.SelectedIndex + 1;
await InsertMapRecord(mapName, mapNotes, defaultZoomLevel);
}
如果您这样做,您应该能够捕获任何异常并进一步调查。
推荐阅读
- google-chrome - 无法使用 MediaSource 在 Firefox 中重播 MP3,即使它在 Chrome 中工作
- r - 如何从R中列表中的循环中分配向量
- mysql - 查询中的问题以查找过去 xx 天内未对任何帖子发表评论的用户
- swiftui - 如何在父视图使用 IgnoringSafeArea() 时访问 safeArea 插图
- javascript - 为什么退出全屏模式后地址栏不显示?
- pandas - 计算列表中每个项目出现在 pandas 数据框列中的次数,用逗号分隔值
- css - 使用粘性标题制作整页滚动条控制表(仅限 CSS)
- java - 为什么 ArrayList 不插入一些值?
- r - 在 R 中将数字转换为日期时遇到问题
- java - 带有单个数据源的 SpringBoot + Batch + Cloud Task @EnableTask 注解导致“序列不存在”问题