c# - 使用 C# Task 进行事件异步操作
问题描述
假设我有一个SomeObj
执行异步操作的对象,它已实现为返回一段数据的事件。
我可能有如下代码:
private void MyFunc1(Func<int> callback)
{
SomeObj obj = SomeObj.GetSomeObj();
obj.onAsyncComplete += callback;
}
因此,在此实现中,回调用于异步接受由 .int
返回的结果数据 (an ) SomeObj.onAsyncComplete
。
我想将此假设示例移至使用async
and await
:
private async int MyFunc1()
{
SomeObj obj = SomeObj.GetSomeObj();
Task<int> asyncCompleteTask = /* something with obj.onAsyncComplete */
await asyncCompleteTask;
return asyncCompleteTask.Result;
}
我将如何完成这样的事情?目标是能够await
将结果int
传递给onAsyncComplete
事件。假设SomeObj
不能修改。
解决方案
我会考虑你为什么首先这样做,因为如果你正在实现另一个库,通常最好坚持他们想要的方法。但是,如果您正在为库创建类似包装器的东西并且真的想改变行为..我会创建一个扩展或包装器方法并使用TaskCompletionSource
:
你MyFunc1
可能看起来像这样:
public Task<int> MyFunc1()
{
SomeObj someObj = new SomeObj();
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
someObj.OnAsynComplete += (r) => tcs.SetResult(r);
someObj.GetSomeObj();
return tcs.Task;
}
或者你可以做一些扩展:
public static class SomeObjExtension
{
public static Task<int> GetResultAsyncTask(this SomeObj someObj)
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
someObj.OnAsynComplete += (r) => tcs.SetResult(r);
someObj.GetSomeObj();
return tcs.Task;
}
}
async void Main()
{
SomeObj someObj = new SomeObj();
int result = await someObj.GetResultAsyncTask();
Console.WriteLine($"Got some number back: {result}");
}
如果您要在没有扩展的情况下运行它,它会遵循您指定的模式:
void Main()
{
SomeObj someObj = new SomeObj();
someObj.OnAsynComplete += (r) => Console.WriteLine($"Got some number back: {r}");
someObj.GetSomeObj();
}
为了测试,我SomeObj
这样创建:
public class SomeObj
{
public void GetSomeObj()
{
Task.Run(async () =>
{
//do something...
await Task.Delay(5000);
OnAsynComplete?.Invoke(new Random().Next(1, 10000));
});
}
public event OnAsyncCompleteHandler OnAsynComplete;
public delegate void OnAsyncCompleteHandler(int result);
}
推荐阅读
- android - 谷歌地方自动完成给出“Cannoat load results !”
- loops - SAS使用带有do循环的迭代变量
- python - 模棱两可的系列的真值
- javascript - 与 Angular 的对话流实现集成未提供正确的回复
- python - 在pyqt5中单击按钮时显示熊猫数据框
- angular - 如何将动态样式应用于列,其中有数字类型值,我想根据值的范围应用颜色
- r - 使用 for 循环遍历目录
- c# - JSON 到 C# 类的无效类型对象具有不一致的数字名称
- html - 设置高度尽可能占用最小宽度的 div
- bash - 尝试通过 docker exec 获取 bash,但没有任何效果(Jaeger 容器)-> OCI 运行时 exec 失败