正确使用TPL / Tasks并了解流程

时间:2015-01-13 01:05:51

标签: c# wpf

使用TPL / Asynchonrous编程完成初学者,但我正试图通过它来处理我正在做的事情。

我有一个调用方法的任务,该方法应继续运行,直到“地址”为止。不是空的。 一旦Address有一些非空值,理想情况下我想创建一个窗口的新实例,并且 让它对用户可见。

我能够按照我的意愿(每5秒钟)运行任务,但我无法弄清楚如何 一旦此操作完成,我就能向用户显示一个新窗口,然后不应该确认'在该表单上给出重新启动'查找'过程

到目前为止,我对使用任务的程序流程感到特别困惑,但我试图实现的目标/我到目前为止所获得的代码如下:

目标:

  • 执行FindTheAddress,直到_profile.Address不再为空
  • 创建一个实例,并使一些WPF窗口可见
  • 加载窗口后,用户必须确认地址是否正确
  • 未能确认我们的开始' FindAddress'再次找到另一场比赛。

为了试图解释,我的代码简化如下:

Task.Factory.StartNew(() => SomeClass.SomeMethod(TimeSpan.FromSeconds(5), ts1.Token));

方法:

public async void FindAddress(TimeSpan interval, CancellationToken token)
{
    while (_profile.Address == null)
    {     
            //FindTheAddress in reality makes an API request (EWS)
            _profile.Address = FindTheAddress();

            if (interval <= TimeSpan.Zero) return;
            await Task.Delay(interval, token);
    }
  //This throws some nasty STA issue I don't really understand.
  (new SomeWindow()).Activate();
}

有关此主题的任何帮助/澄清,我已尝试通过MSDN文档但我没有发现它们非常可消化。

2 个答案:

答案 0 :(得分:1)

我在这里根本不需要后台线程,除非FindTheAddress是CPU密集型的(我无法想象)。

因此,您可以使用常规async / await。您应avoid async void(正如我在MSDN文章中所述)。这意味着您的工作方法如下所示:

public async Task FindAddressAsync(TimeSpan interval, CancellationToken token)
{
  while (_profile.Address == null)
  {     
    _profile.Address = FindTheAddress();

    if (interval <= TimeSpan.Zero) return;
    await Task.Delay(interval, token);
  }
}

然后,无论从这个过程开始(按钮点击等),只需使用await

await FindAddressAsync(TimeSpan.FromSeconds(5), ts1.Token);
(new SomeWindow()).Activate();

答案 1 :(得分:1)

如果没有完整的代码示例,我们真的不清楚这里需要什么。但是,FindAddress(TimeSpan, CancellationToken)方法的以下版本中没有任何内容可以阻止,因此即使您从UI线程调用它(因为您应该),也可以保证工作:

public async Task FindAddress(TimeSpan interval, CancellationToken token)
{
    while ((_profile.Address = await Task.Run(() => FindTheAddress())) == null)
    {     
            if (interval <= TimeSpan.Zero) return;
            await Task.Delay(interval, token);
    }
  //This throws some nasty STA issue I don't really understand.
  (new SomeWindow()).Activate();
}

这确保即使无参数FindTheAddress()方法耗时(例如,返回需要五秒),它也不会阻止UI线程。该操作将在不同的线程中运行,并在UI线程中自动执行继续。

请注意,我还调整了代码,以便它不会不必要地失败(即如果延迟为零但第一次调用成功),并且它不会添加不必要的延迟(即通过调用{{ 1}}即使该方法返回一个非空值)。