2014-09-24 48 views
3

我有一个WPF应用程序,其中查看模型中的某个属性将填充为对服务的调用。到目前为止,我一直在关注Stephen Cleary的优秀教程。他讨论了这样做的一种方法here多次调用异步方法

在我的情况下,视图模型每个应用程序实例化一次。应用程序在视图模型上调用Initialise方法(自定义方法),传递一些信息,View模型应该根据这些信息与服务联系以获取实例化的属性。

问题是应用程序可以多次调用Initialise方法(用户随机移动)传递一组新信息。发生这种情况时,我需要放弃早先运行的任务(如果有的话),这些任务在上次调用Initialise时调用该服务,并用新的一组信息调用该服务,并确保该属性仅绑定到最新调用的结果。

有人可以帮助想出一个模式来实现这一目标吗?基本上多次调用一个异步方法,但只保留最后的结果。

+0

你会同时多次打电话给他们吗?或者你的应用程序会调用'Initialize'方法几次,但是在调用之间有差异? – 2014-09-24 12:50:56

+0

当用户单击按钮时会调用初始化方法,这样调用将不会是并发的,而是顺序的。 – Nikhil 2014-09-24 12:53:09

回答

1

基本上,您要取消以前调用Initialize方法。而在TPL中,如果你想取消某些东西,你通常应该使用CancellationToken

您可以这样做的方式是在您的视图模型中有一个CancellationTokenSource类型的字段,表示取消最后一次调用Initialize。当您运行Initialize时,它将取消先前的调用,设置自己的取消,调用服务,然后只在未请求取消时才设置属性。在代码:

class ViewModel 
{ 
    // default value just to avoid a null check 
    private CancellationTokenSource intializationCancellation = 
     new CancellationTokenSource(); 

    public async Task InitializeAsync(int parameter) 
    { 
     // cancel previous initialization, if any 
     intializationCancellation.Cancel(); 

     var cts = new CancellationTokenSource(); 
     intializationCancellation = cts; 

     var value = await GetValueaAsync(parameter); 

     if (cts.Token.IsCancellationRequested) 
      return; 

     Value = value; 
    } 

    private async Task<string> GetValueAsync(int parameter) 
    { 
     // call the external service here 
    } 

    public string Value { get; private set; } 
} 

如果服务你调用支持取消,你应该通过CancellationToken它太,这很可能节省一些资源。如果你这样做,不要忘记赶上OperationCanceledException(因为我相信你不希望Initialize抛出,即使它被取消)。

+0

你的答案是正确的,但不适用于我的问题。鉴于COM Interop的高级别,我也不得不处理,有没有直接的模式,可以帮助解决这个问题。事情也很复杂,因为我需要确保运行任务的线程是TPL不能保证的STA。总而言之,我不得不重新设计一点点,但我现在有一些工作要做。无论如何谢谢你! – Nikhil 2014-11-14 03:41:16