gpt4 book ai didi

C# 等待 lambda 回调完成

转载 作者:行者123 更新时间:2023-11-29 06:26:03 27 4
gpt4 key购买 nike

摘要

我目前正在尝试使用 MySQL 数据库来执行 select 语句并以回调的方式将其返回到匿名语句 lambda。这就是这个特定的(大部分未记录的)库处理请求的方式。我还需要等待这个过程完成。

我目前正在尝试使用async方法,但是任务的完成似乎被断言得太早(即await taskName;在回调之前被绕过已完成,因此返回的 Dictionary 为空)。

我尝试使用完成标志方法,其中使用 bool 标志来表示回调是否已完成,并在返回任务之前在 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执行响应控制台输出后不久,第二行读取Executed select statements with x rows是输出。 这里的主要问题是存在竞争条件。如何确保数据在处理之前正确填充?

最佳答案

您需要一种方法让数据库回调向您的代码发出信号,表明它已被调用,并且可以恢复执行。最简单的方法是使用 TaskCompletionSource 。它看起来像:

public async Task<Dictionary<int, object>> ExecuteSelectAsync (string statement)
{
// declare the TaskCompletionSource that will hold the database results
var tcs = new TaskCompletionSource<Dictionary<int, object>>();

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");

var data = new Dictionary<int, object>();
// build your dictionary here

// the work is now complete; set the data on the TaskCompletionSource
tcs.SetResult(data);
})
);

// wait for the response data to be created
var responseData = await tcs.Task;

Utility.LogDebug("Database", "Returning select execution response");
return responseData;

// if you don't need the logging, you could delete the three lines above and
// just 'return tcs.Task;' (or move the logging into the callback)
}

关于C# 等待 lambda 回调完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59459912/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com