编程语言
首页 > 编程语言> > c# – 用于立即返回内容的异步方法的模式

c# – 用于立即返回内容的异步方法的模式

作者:互联网

如果我写一个简单的函数,我可以立即得到一个结果.如果我使用async / await并返回一个Task – 该方法将在完成任务时返回,但是如果我需要编写一个需要立即返回的方法,然后继续更新结果并可能最终完成任务该怎么办? ?另外,如果我想在WinRT组件库之外公开它以供其他语言的组件使用,该怎么办?我如何在C#中完成它,我将如何在C/C++X中完成?或JS或许?

例1:

我想公开一个返回ImageSource的属性,这样我就可以立即将它从我的MVVM视图模型绑定到XAML视图.加载ImageSource的方法将放在一个单独的类中,该类暴露在WinRT组件之外(它是一个公共方法).现在我希望该方法是可以等待的,或者至少以某种方式返回我可以等待的任务,但也会立即返回ImageSource,因此我调用它的属性可以立即返回,因为属性不能是异步的.调用者不知道ImageSource将是什么类型,因此无法实例化它,因为ImageSource实际上是一个抽象类型,通常表示为BitmapImage或WriteableBitmap,在我的情况下,两者都可以从方法返回.显然,该方法本身立即知道它是否将返回任何类型的对象,但是它需要一些时间来读取/创建和/或解码图像.

我在想C#中的签名可能是这样的

public async Task<ImageSource> GetImage(
    object key,
    out ImageSource bitmap,
    CancellationToken cancellationToken)

我只是不等待属性访问器中的方法的结果,但我想我能够立即返回位图参数,而当我在其他地方调用或在我的视图模型的代码中的其他地方事件时我会能够等待或取消任务.

例2:

我希望能够列出磁盘中的文件,并在列出所有文件后获得完成的任务,但会立即返回一个IObservableVector视图模型,表示在我的XAML UI中使用的文件,这些文件更新为文件页面异步加载.

在这里,我可能会做类似的事情:

public async Task<int> GetImages(
    object queryParemeters,
    out ObservableCollection<CustomFileInfoType> files,
    CancellationToken cancellationToken)

问题

现在上面看起来差不多好了,但是我觉得我不能在WinRT组件之外暴露一个TPL任务,因为Task不是WinRT类型,所以我可能给了一个像上面这样的内部方法和一个包含它的公共方法通过调用AsyncInfo.Run()作为IAsyncOperation,传递任务和取消令牌. ObservableCollection也只是.NET,所以我可能需要在它周围创建一个实现IObservableVector的包装器,因为我不认为它在.NET中可用.这些可能存在其他潜在问题,我不确定这种设计是否正确.

那么 – 我将如何在C/C++X中完成所有这些工作?还是JS?

解决方法:

async建立在异步操作的概念之上,具有明确的开始和结束.最后,可能会有一个结果.而已.请注意,异步方法可能没有参数,因为它们不适合此模型.

如果你想要一个值流,那么使用Reactive Extensions.有一个有趣的RxUI library很好地将可观察量与MVVM模式结合在一起.

也就是说,我认为你的任何一个例子都不需要观察(尽管如果你愿意,你当然可以转移到Rx).我解决了你的第一个例子(数据绑定的异步属性)on my blog;简短的回答是使用Task< T>的包装器.实现INotifyPropertyChanged like this one

// Service
public async Task<ImageSource> GetImage(object key, CancellationToken cancellationToken);

// ViewModel
INotifyTaskCompletion<ImageSource> Image { get; private set; }
...
Image = NotifyTaskCompletion.Create(GetImage(key, token));

// View
<Image Source="{Binding Image.Result}" />

关于您的第二个示例,通过将新项目视为异步方法的进度更新,可以非常轻松地完成此操作:

// Service
public async Task<int> GetImages(object queryParemeters,
    CancellationToken cancellationToken,
    IProgress<CustomFileInfoType> progress);

// ViewModel
var collection = new ObservableCollection<CustomFileInfoType>();
var progress = new Progress<CustomFileInfoType>(x => collection.Add(x));
await GetImages(query, token, progress);

暴露这些类型完全是另一回事. WinRT组件必须公开WinRT类型.我建议您使用pure async / await编写基本逻辑(服务和可能的ViewModel),然后单独进行翻译.正如您所指出的,AsyncInfo.Run会将Task转换为IAsyncOperation,并且没有用于ObservableCollection到IObservableVector的内置转换器(虽然它不难编写,并且有几个可通过Google获得).

Then also – how would I do all this in C++/CX? Or JS?

我不知道那个.您可能必须在这些平台上编写自己的NotifyTaskCompletion等效项,或者只使用回调.

标签:c,async-await,windows-runtime,c-cx,winrt-component
来源: https://codeday.me/bug/20190612/1226484.html