如何等待从异步方法(C#)接收回调
我有一个从Firebase获取一些值的方法,如下所示:如何等待从异步方法(C#)接收回调,c#,unity3d,asynchronous,task,C#,Unity3d,Asynchronous,Task,我有一个从Firebase获取一些值的方法,如下所示: void getTable(Action<IDictionary> callBack) { // function & data initialized here function.CallAsync(data).ContinueWith((callTask) => { if (callTask.IsFaulted)
void getTable(Action<IDictionary> callBack)
{
// function & data initialized here
function.CallAsync(data).ContinueWith((callTask) =>
{
if (callTask.IsFaulted)
callBack(null);
else if (callTask.IsCompleted)
{
Debug.Log("I am being executed when done");
var result = (IDictionary) callTask.Result.Data;
callBack(result);
}
});
}
预期产出:
我试图在GetTable方法的lambda表达式中分配“valueReturned”。但它给出了错误:“不能在lambda表达式中使用ref参数”考虑从
getTable
返回Task
,并在getTable
中等待它:
Task getTable(Action<IDictionary> callBack)
{
// function & data initialized here
return function.CallAsync(data).ContinueWith((callTask) =>
{
if (callTask.IsFaulted)
callBack(null);
else if (callTask.IsCompleted)
{
Debug.Log("I am being executed when done");
var result = (IDictionary) callTask.Result.Data;
callBack(result);
}
});
}
public Task<string> GetTable()
{
string val = await getTable((dictionary =>
{
Debug.Log("Done getting values");
val = (string) dictionary["someValue"]; // returns "testValue" to val
}));
Debug.Log("Value is:" + val);
Debug.Log("Completed Execution");
return val;
}
任务可获取(操作回调)
{
//函数和数据在此初始化
return function.CallAsync(data).ContinueWith((callTask)=>
{
if(callTask.IsFaulted)
回调(空);
else if(callTask.IsCompleted)
{
Log(“完成时我正在执行”);
var result=(IDictionary)callTask.result.Data;
回调(结果);
}
});
}
公共任务GetTable()
{
字符串val=wait getTable((字典=>
{
Log(“获取值完成”);
val=(字符串)字典[“someValue”];//将“testValue”返回给val
}));
Log(“值为:”+val);
Debug.Log(“已完成的执行”);
返回val;
}
否则,您的getTable
方法将启动一个任务并继续执行,因此getTable
将null
赋值给valueReturned
(假设CallAsync
运行的时间足够长)并继续执行。我还想说,您可以从getTable
返回Task
如果出于某种原因,您无法使代码异步,那么根据您的上下文,有多种选择,其中一些可能比其他更合适,但无论哪种方法,您都应谨慎处理。编写getTable
的更惯用方法是:
async Task getTable(Action<IDictionary> callBack)
{
IDictionary result;
try
{
result = await function.CallAsync(data);
}
catch
{
result = null;
}
callback(result);
}
异步任务可获取(操作回调)
{
词典结果;
尝试
{
结果=wait function.CallAsync(数据);
}
抓住
{
结果=空;
}
回调(结果);
}
(这是否真的是一个好主意是另一个问题,因为您牺牲了错误信息,而将异步方法转换为回调通常是毫无意义的…)
但是您的GetTable
方法注定要失败。您永远不能在输出参数中返回异步调用的结果,因为在内部调用完成之前,外部函数已经退出。唯一可行的方法是GetTable
在GetTable
上执行阻塞等待,这首先破坏了使用异步的整个要点
唯一真正的答案是,您当前的设计是错误的,您需要以不同的方式进行。异步始终是唯一的方法。如果我们将您的私有方法剥离到核心,那么只不过是这样:
private async Task<IDictionary> getTable()
{
// function & data initialized here
var result = await function.CallAsync(data);
return result?.Data;
}
public async Task<string> GetTable()
{
var dictionary = await getTable();
var valueReturned = (string)dictionary["someValue"]; // returns "testValue" to val
Debug.Log("Value is:" + valueReturned);
Debug.Log("Completed Execution");
return valueReturned;
}
正如@Miral所说:“这种设计是错误的”。从asyn/await的角度来看,我们可以将两个函数重构为一个简单的异步方法:
public async Task<string> GetTableAsync()
{
// <function & data initialized here>
var result = await function.CallAsync(data);
var dictionary = result?.Data;
return dictionary == null ? null: (string)dictionary["someValue"];
}
公共异步任务GetTableAsync()
{
//
var result=await function.CallAsync(数据);
var字典=结果?数据;
返回dictionary==null?null:(字符串)dictionary[“someValue”];
}
您的函数.CallAsync(data).ContinueWith
不等待,这就是为什么您在“完成获取值”之前获得“已完成的执行”。正如@Miral提到的:将异步方法转换为回调是毫无意义的。
public void GetTable(ref string valueReturned)
{
var dictionary = getTable().Result;
valueReturned = (string)dictionary["someValue"]; // returns "testValue" to val
Debug.Log("Value is:" + valueReturned);
Debug.Log("Completed Execution");
}
public async Task<string> GetTableAsync()
{
// <function & data initialized here>
var result = await function.CallAsync(data);
var dictionary = result?.Data;
return dictionary == null ? null: (string)dictionary["someValue"];
}