【问题标题】:Awaiting a method that is deeply nested on stack等待一个深度嵌套在堆栈上的方法
【发布时间】:2013-10-17 00:06:23
【问题描述】:

假设在某个时候至少有 10 个方法在堆栈中可用,但尚未完成。其中许多方法都在处理对 UI 产生影响的操作。此时,我想发出一个保存命令。保存命令可以成功完成,也可以失败。根据结果​​,我想做不同的操作,然后才返回执行到那些留在堆栈上的方法。

现在,如果我同步运行保存命令,没有问题。我想异步执行Save命令,将执行返回到消息泵(UI),而堆栈上的所有代码(方法)都应该等待SaveCommand完成。

现在,据我了解等待,不能保证会在同一个线程(在我的情况下为 UI 线程)上进行调用。所以,我不能只等待被调用的第一个方法(堆栈中所有其他方法的父方法),因为如果启动不同的线程,它将引发 UI 异常(从不同的线程访问 UI 元素)。

那么,如何处理这种情况呢?示例代码:

public bool PropertyName {get; set { MethodA(); // some code after  };}
public void MethodB() { MethodC(); // some code after  } 
public void MethodC() { MethodD(); // some code after  } 
public void MethodD() { MethodE(); // some code after  } 
// etc

void MEthodK()
{
    Save();
}

【问题讨论】:

  • 你应该告诉我们你正在使用什么语言/框架/等
  • 我已经更新了这个问题。这些方法不一定是方法,它们可以是函数,只是为了清楚起见是无效的。

标签: c# wpf c#-4.0 async-await


【解决方案1】:

如果您想(异步)等待某个方法,只需 await 从该方法返回的 Task

public async Task MethodCAsync() { await MethodDAsync(); // some code after  } 
public async Task MethodDAsync() { await MethodEAsync(); // some code after  } 
async Task MethodKAsync()
{
  await Save();
}

这将导致您的属性设置器出现问题,现在必须是异步方法:

public bool PropertyName { get; private set; }
public async Task SetPropertyNameAsync() { await MethodAAsync(); // some code after }

【讨论】:

  • 那么,您的建议是等待所有方法,尽管我只需要等待一个?这是我的第一个念头,但艰难本身让我后退了一步。这实际上意味着我的大多数方法都是异步的......我希望会有某种 awaitX 方法,它会立即将控制权返回给消息泵,而不是之前的调用者,并且当任务被标记为完成时,那么泵将在 await 关键字之后立即返回执行。
  • @Goran 这就是它的作用,它只需要一切都是异步的才能工作。
  • 我了解 async await 的工作原理,但我只是不喜欢到处都有它的想法。是否存在一些性能问题?有其他选择吗?
  • @Goran:在调用堆栈中一直使用async async 的工作方式。没有任何真正的性能问题。替代方案包括任何其他类型的asynchronous pattern,但所有其他模式要复杂得多,并且仍然需要您以比设置async 更剧烈的方式更改调用堆栈中的每个方法。
【解决方案2】:

除非您从 UI 线程调用 ConfigureAwait(),否则 awaitTask 将始终继续在 UI 线程上运行您的代码。
您不必担心。

【讨论】:

  • 所以,在我刚刚添加的代码中,您对正确方法的建议是什么(在不阻塞 UI 线程的情况下运行 MethodK,并强制所有其他方法(A-K)等待 Save 完成?)?
  • @Goran:将所有这些方法设为asyncawait,无论何时调用它们。
猜你喜欢
  • 1970-01-01
  • 2011-08-13
  • 2021-05-02
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多