【问题标题】:Calling an async method multiple times多次调用异步方法
【发布时间】:2014-09-24 11:57:00
【问题描述】:

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

在我的例子中,每个应用程序都会实例化一次视图模型。应用程序在视图模型上调用 Initialise 方法(自定义方法),传递一些信息,在这些信息的基础上,视图模型应该联系服务以实例化属性。

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

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

【问题讨论】:

  • 你会同时调用他们多次吗?还是您的应用程序会多次调用Initialize 方法,但调用之间存在差异?
  • initialise 方法在用户单击按钮时被调用,因此调用不会是并发的,而是顺序的。

标签: c# task-parallel-library


【解决方案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 抛出,即使它被取消了)。

【讨论】:

  • 您的答案是教科书正确的,但并不真正适用于我的问题。鉴于我还必须处理高级别的 COM 互操作,没有直接的模式可以帮助解决这个问题。事情也很复杂,因为我需要确保运行任务的线程是 TPL 不能保证的 STA。总而言之,我必须重新设计一些东西,但我现在可以按照我的意愿工作。还是谢谢你!
猜你喜欢
  • 2018-12-11
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
相关资源
最近更新 更多