开始一个任务并稍后多次等待

12

在一个移动应用程序中,我有一个可能会很长的异步操作(多个异步网络调用分组在一个异步函数中)。

_myClassField = myClient.DoANumberOfNetworkCallsAsync();

我在应用启动时立即执行调用,然后显示闪屏界面和欢迎界面。仅在第一次用户交互(例如:按下按钮)时,最终等待任务,并使用户等待响应如果未准备就绪。

public async Task<object> GetMyLongAwaitedObjectAsync()
{
    return await _myClassField;
}

这种方法可以被多次调用,可能来自UI线程和非UI线程。

这会导致问题吗?还是这是一种有效的模式?


这看起来有问题。你也必须将 DoANumberOfNetworkCallsAsync() 设为异步。你能展示一下在这个类中如何填充字段的方式吗? - Kosala W
我们需要更多的上下文信息:框架?平台? - Giulio Caccin
Kosala,DoANumberOfNetworkCallsAsync()正如其名称所示是异步的,但它没有被等待以便在后台工作。只有在稍后等待返回的任务。该框架是.Net 4.5或更高版本,平台可以是任何(Windows桌面/手机等)。 - Pinco Pallino
@PincoPallino 这是WinForms吗?如果是的话,这会导致UI线程挂起,等待结果。 - Kosala W
@KosalaW -- 即使从一个 async void 事件处理程序中调用 GetMyLongAwaitedObjectAsync(),它也能正常工作吗?(我们不知道是谁在调用这个东西)-- 我认为处理程序会一直运行到此处的 await,然后返回到 UI 线程,直到任务完成... (?) - Code Jockey
1个回答

16

完成的任务可以被等待多次,它总是返回相同的结果。

你也可以调用Wait()Result多次,它们在任务完成后不会阻塞。

我会对你的代码进行一个修改:

public Task<object> GetMyLongAwaitedObjectAsync()
{
    return _myClassField;
}

这样,编译器就不必生成状态机,每次调用属性时也不会实例化一个状态机。


1
楼主在这里询问此方法是否存在任何问题。您能否考虑提及未处理的异常? - Giulio Caccin
异常可能仍然会被调用 GetMyLongAwaitedObjectAsync() 的调用者捕获。 - Paulo Morgado
但是更可取的是调用.Result还是使用await呢?如果开发人员确信在代码的那个位置任务已经完成 - Марк Павлович
1
如果“开发人员确信在那段代码中的任务已经完成”,那么Result可以安全使用。 - Paulo Morgado
1
不确定这是否是最终答案。请查看此处,这是一个示例,展示了如何使用Task.WaitAll(task1, task2, task3, task4, task5);立即调用5个任务,并稍后等待它们完成。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接