代码之家  ›  专栏  ›  技术社区  ›  dotNET

有条件地等待任务

  •  0
  • dotNET  · 技术社区  · 5 年前

    为了一个 async Task<bool> ,我需要在方法完成时采取一些操作。异步方法如下所示:

    async Task<bool> EntryExists(string entry)
    {
      return await Task.Run(() => call_that_returns_bool());
    }
    

    我打电话给它,并给它附加了一个后续任务来执行后续操作:

    EntryExists(my_entry).ContinueWith(t =>
    {
      if(t.Result) ...
    });
    

    有条件地 等待链接的任务完成。这意味着取决于一个参数,我要么需要立即返回调用方,要么等待任务完成。我将上面的代码更改为如下所示:

    var T = EntryExists(my_entry).ContinueWith(t =>
    {
      if(t.Result) ...
    });
    
    if(wait) T.Wait(); //wait is my parameter
    

    wait 参数是 true

    var T = EntryExists(my_entry).ContinueWith(t =>
    {
      if(t.Result) ...
    });
    
    T.Start();
    if(wait) T.Wait();
    

    它告诉我

    不能对连续任务调用Start

    我知道我遗漏了一些基本的东西,但是在过去15个小时的编码之后,我的大脑并没有太大帮助。有人能指出我需要做什么吗?

    0 回复  |  直到 5 年前
        1
  •  1
  •   gandaliter    5 年前

    You shouldn't block on async code . 简而言之,您很可能会阻塞异步方法需要返回的线程(在本例中,您是,因为它是UI线程)。解决方案是一直使用async await,而不是尝试同步运行它。如果您必须提供同步方法,那么至少提供尽可能简单的包装器,而不是混合 ContinueWith

    您的外部呼叫可以重写为:

    async Task<{something}> MakeCallAndContinue()
    {
        try
        {
            await EntryExists(my_entry);
            // additional continuation code
        }
        catch (Exception e)
        {
            // handle in some way
        }
    }
    var task = MakeCallAndContinue();
    if (wait) await task;
    

    想开始一项任务却不等待是不寻常的,这就是你正在做的如果 wait 是假的。我在上面的代码中放入的错误处理程序是为了确保不会向未等待的任务引发异常。如果您这样做了,那么它将被抛出到其他地方,如果您没有声明全局处理程序,则可能会终止您的进程。

    您将无法在WPF命令中按原样使用上面的命令,因为它是异步的。但是,可以使用异步WPF命令处理程序,如前所述 here . 如果你真的想同时做,那么你需要打电话给 .Wait() ,但正如斯蒂芬·克利里在我的第一个链接中所解释的,你必须使用 ConfigureAwait(false) 在所有等待的任务上一直向下,以防止其中一个任务试图返回到占用的UI线程,并死锁。