如何使用同步方法将异步方法中的 return 值传递到同步 class 中
How to pass an return value from an aysnchronous method into a synchronous class with a synchronous method
我有一个正在引用的 .DLL,它被异步编码以调用 API。我别无选择使用这个异步 API 因为我不是它的编码者。在这个 DLL 中有一个名为 CreateFqrs 的异步方法,returns 类型为 Task'<'List'<'JciFqr>>。我在非异步 class 中有一个名为 ParseHL7Fqr 的方法,它接受 List。
当我单步执行我的代码时,我遇到了这部分代码并且代码死锁。我已经阅读了 Cleary 关于 Async 死锁的文章,我似乎无法找到一种方法来解决我的方法和 classes Async 的问题,我真的不需要这样做。
这是下面的代码,是的,我知道 .Result 导致我的代码死锁。如果您需要更多代码,请告诉我。
Task<List<JciFqr>> objPtFqr = new Task<List<JciFqr>>();
objPtFqr = eventEngine.CreateFqrs(eventEngine.siteDirector, eventEngine.path,
eventEngine.username, eventEngine.password, eventEngine.objName);
parseCode = hl7Event.ParseHL7Code(content, "Code_Blue",
hl7Event.searchItem1, hl7Event.searchItem2, ref roomNumber, ref codeType);
if (parseCode)
{
parseFqr = hl7Event.ParseHL7Fqr(objPtFqr.Result, roomNumber, codeType,
ref parsedObjPtFqr);
}
你可以通过将你的调用委托给一个没有同步上下文的线程池线程来摆脱困境:
var delegatedTask = Task.Run(async () =>
{
var objPtFqr = await eventEngine.CreateFqrs(eventEngine.siteDirector, eventEngine.path,
eventEngine.username, eventEngine.password, eventEngine.objName).ConfigureAwait(false);
parseCode = hl7Event.ParseHL7Code(content, "Code_Blue",
hl7Event.searchItem1, hl7Event.searchItem2, ref roomNumber, ref codeType);
if (parseCode)
{
parseFqr = hl7Event.ParseHL7Fqr(objPtFqr.Result, roomNumber, codeType,
ref parsedObjPtFqr);
}
});
delegatedTask.Wait();
请注意,我建议您将此作为任何类型的最后手段。让异步在你的代码库中增长绝对是可取的。
至于异常处理,传递的委托中发生的任何异常都将用 AggregateException
包装,您需要将其解包。
Yuval 的回答有效,但在评论中您表示要使用 ref
。在调入库并等待任务完成之前,您可以将当前同步上下文设置为 null。之后一定要恢复同步上下文。
这是一个您可能应该记录下来的 hack。
我有一个正在引用的 .DLL,它被异步编码以调用 API。我别无选择使用这个异步 API 因为我不是它的编码者。在这个 DLL 中有一个名为 CreateFqrs 的异步方法,returns 类型为 Task'<'List'<'JciFqr>>。我在非异步 class 中有一个名为 ParseHL7Fqr 的方法,它接受 List。
当我单步执行我的代码时,我遇到了这部分代码并且代码死锁。我已经阅读了 Cleary 关于 Async 死锁的文章,我似乎无法找到一种方法来解决我的方法和 classes Async 的问题,我真的不需要这样做。
这是下面的代码,是的,我知道 .Result 导致我的代码死锁。如果您需要更多代码,请告诉我。
Task<List<JciFqr>> objPtFqr = new Task<List<JciFqr>>();
objPtFqr = eventEngine.CreateFqrs(eventEngine.siteDirector, eventEngine.path,
eventEngine.username, eventEngine.password, eventEngine.objName);
parseCode = hl7Event.ParseHL7Code(content, "Code_Blue",
hl7Event.searchItem1, hl7Event.searchItem2, ref roomNumber, ref codeType);
if (parseCode)
{
parseFqr = hl7Event.ParseHL7Fqr(objPtFqr.Result, roomNumber, codeType,
ref parsedObjPtFqr);
}
你可以通过将你的调用委托给一个没有同步上下文的线程池线程来摆脱困境:
var delegatedTask = Task.Run(async () =>
{
var objPtFqr = await eventEngine.CreateFqrs(eventEngine.siteDirector, eventEngine.path,
eventEngine.username, eventEngine.password, eventEngine.objName).ConfigureAwait(false);
parseCode = hl7Event.ParseHL7Code(content, "Code_Blue",
hl7Event.searchItem1, hl7Event.searchItem2, ref roomNumber, ref codeType);
if (parseCode)
{
parseFqr = hl7Event.ParseHL7Fqr(objPtFqr.Result, roomNumber, codeType,
ref parsedObjPtFqr);
}
});
delegatedTask.Wait();
请注意,我建议您将此作为任何类型的最后手段。让异步在你的代码库中增长绝对是可取的。
至于异常处理,传递的委托中发生的任何异常都将用 AggregateException
包装,您需要将其解包。
Yuval 的回答有效,但在评论中您表示要使用 ref
。在调入库并等待任务完成之前,您可以将当前同步上下文设置为 null。之后一定要恢复同步上下文。
这是一个您可能应该记录下来的 hack。