使用TPL / Asynchonrous编程完成初学者,但我正试图通过它来处理我正在做的事情。
我有一个调用方法的任务,该方法应继续运行,直到“地址”为止。不是空的。 一旦Address有一些非空值,理想情况下我想创建一个窗口的新实例,并且 让它对用户可见。
我能够按照我的意愿(每5秒钟)运行任务,但我无法弄清楚如何 一旦此操作完成,我就能向用户显示一个新窗口,然后不应该确认'在该表单上给出重新启动'查找'过程
到目前为止,我对使用任务的程序流程感到特别困惑,但我试图实现的目标/我到目前为止所获得的代码如下:
目标:
为了试图解释,我的代码简化如下:
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文档但我没有发现它们非常可消化。
答案 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}}即使该方法返回一个非空值)。