【发布时间】:2019-12-23 18:42:49
【问题描述】:
总结
我目前正在尝试使用 MySQL 数据库库来执行 select 语句并以回调的方式将其返回到匿名语句 lambda。这就是这个特定的(大部分未记录的)库处理请求的方式。我也需要等待这个过程完成。
我目前正在尝试使用async 方法,但是似乎过早断言任务完成(即在回调完成之前绕过await taskName;,因此返回的字典为空)。
我曾尝试使用完成标志方法,其中使用布尔标志来表示回调是否已完成,并在返回任务之前在 while 循环中使用 Task.Yield()。
下面是来自两个不同类的两个函数。第一个来自数据库类,第二个来自实用程序类(从中调用数据库类)。
代码
/// <summary>
/// Asynchronously executes a select MySQL statement and returns a dictionary of rows selected.
/// </summary>
/// <param name="statement"></param>
/// <returns></returns>
public async Task<Dictionary<int, object>> ExecuteSelectAsync (string statement)
{
// Init dictionary of rows and counter for each row
Dictionary<int, object> responseData = new Dictionary<int, object>();
int i = 0;
bool complete = false;
DatabaseLibrary.execute(
statement,
new Action<dynamic> (s =>
{
// Take the data returned as 's' and populate the 'responseData' dictionary.
Utility.LogDebug("Database", "Executed select statement with " + numberOfRows.ToString() + " rows");
})
);
Utility.LogDebug("Database", "Returning select execution response"); // By this point, the lambda expression hasn't been executed.
return responseData; // This is empty at time of return.
}
/// <summary>
/// Checks the supplied data against the database to validate.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static async Task<bool> ValidateData(string data)
{
Database database = new Database();
Task<Dictionary<int, object>> selectTask = database.ExecuteSelectAsync("SELECT fieldname FROM tablename WHERE data='" + data + "'"); // Excuse statement forming, this is just to test
await selectTask;
try
{
Dictionary<string, object> firstRow = (Dictionary<string, object>)selectTask.Result[0];
if ((int)firstRow["fieldname"] == 0) return false; // data not valid, return false
else return true; // data valid, return true
}
catch (Exception e)
{
LogException("Utility", e);
LogDebug("Utility", "Database class returned empty result set");
return false; // Empty result, presume false
}
}
我知道这段代码有效,在显示Returning select execution response 控制台输出后不久,输出第二行读取Executed select statement with x rows。 这里的主要问题是存在竞争条件。如何确保在处理数据之前正确填充数据?
【问题讨论】:
-
我不认为共享可以识别竞争条件的代码。
execute()方法里面有什么? -
execute() 方法隐藏在 JavaScript 库中。这是将语句传递给 MySQL 并处理响应的地方。
-
DatabaseLibrary.execute是否返回Task?如果是这样,您应该使用await DatabaseLibrary.execute(...)来“暂停”您的方法,直到数据库执行完成。 -
@BradleyGrainger 我已经尝试过了,但是
DatabaseLibrary.execute是在运行时确定的(通过导出调用),awaiting 它会导致 RuntimeBinderException(无法执行运行时绑定在空引用上)。
标签: c# mysql asynchronous lambda callback