我使用TPL实现了一个简单的任务。等待10秒钟执行并返回true / false。
var checkCFOPTask = Task.Run(() => CheckCFOPExists());
checkCFOPTask.Wait(TimeSpan.FromSeconds(10));
if (checkCFOPTask.Result)
{
}
else
{
}
问题是我的代码卡在if语句中。
if (checkCFOPTask.Result)
每次我暂停调试器时,它仍然在等待上面的代码行。这是第一次发生。理想情况下,它应该在10秒内返回true / false。
以下是功能定义 -
CheckCFOExists:由任务执行。
private bool CheckCFOPExists()
{
bool found = false;
try
{
while (!found)
{
try
{
if (ieDriver.FindElement(By.Id("popup_message")).Text == "Não existem itens para realizar o rateio.")
{
ResetInvoiceSearchScreen();
break;
}
}
catch (Exception ex)
{
}
try
{
if (arrCFOPList.Contains(ieDriver.FindElement(By.Id("vendorNF.cfopOperCode")).GetAttribute("value")))
{
found = true;
}
}
catch (Exception ex)
{
}
}
}
catch (Exception ex)
{
}
return found;
}
ResetInvoiceSearchScreen:在上述功能中执行
private void ResetInvoiceSearchScreen()
{
try
{
ieDriver.FindElement(By.Id("popup_ok")).Click();
ieDriver.FindElement(By.Id("ltmCnpjCpf")).Clear();
ieDriver.FindElement(By.Id("notaFiscalNbr")).Clear();
ieDriver.FindElement(By.Id("inbNotaFiscalId")).Clear();
ieDriver.FindElement(By.Id("seriesFrmCd")).Clear();
}
catch (Exception ex)
{
}
}
是否还需要其他功能以确保功能正常超时?如果我能提供更多细节,请告诉我。
修改
我在Visual Studio的即时窗口中看到checkCFOPTask.Result
的以下消息 -
Id = Cannot evaluate expression because the code of the current method is optimized., Status = Cannot evaluate expression because the code of the current method is optimized., Method = Cannot evaluate expression because the code of the current method is optimized., Result = Cannot evaluate expression because the code of the current method is optimized.
答案 0 :(得分:1)
看起来您需要为正在调用的方法添加超时支持 - 因为如果找不到它正在寻找的东西,它将永远循环。
最简单的方法是将CancellationToken
传递给方法。您还应该将测试代码分解为一个返回bool的单独方法。
另请注意,您有一个繁忙的循环,这在轮询时通常不是一个好主意!如果您正在轮询的内容不可用,最好在轮询时引入一个小睡眠。 (注意:如果您有更好的方法来检查某些内容,一般来说轮询并不是一个好方法,但它看起来不像您可以在这里使用的任何其他内容,因此轮询将不得不这样做。)
你可以像这样编写你的方法(我省略了为你专注于其他逻辑而轮询你正在寻找的东西的代码):
private bool CheckCFOPExists(CancellationToken cancel)
{
TimeSpan retryDelay = TimeSpan.FromMilliseconds(500);
while (true)
{
if (tryToFindTheThing()) // Blocking call.
return true;
if (cancel.WaitHandle.WaitOne(retryDelay))
return false;
}
}
bool tryToFindTheThing()
{
return false; // Your implementation goes here.
}
然后调用它并有10秒的超时你会做这样的事情(可编辑的控制台应用程序):
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static void Main()
{
var test = new Program();
// Create a cancellation token source that cancels itself after 10 seconds:
var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(10));
// Create and run the task:
var sw = Stopwatch.StartNew();
var checkCFOPTask = Task.Run(() => test.CheckCFOPExists(cancellation.Token));
Console.WriteLine("Waiting for task to finish.");
Console.WriteLine($"Task returned: {checkCFOPTask.Result} after {sw.ElapsedMilliseconds} ms");
}
private bool CheckCFOPExists(CancellationToken cancel)
{
TimeSpan retryDelay = TimeSpan.FromMilliseconds(500);
while (true)
{
if (tryToFindTheThing()) // Blocking call.
return true;
if (cancel.WaitHandle.WaitOne(retryDelay))
return false;
}
}
bool tryToFindTheThing()
{
return false; // Your implementation goes here.
}
}
}
答案 1 :(得分:0)
在使用结果之前,您需要使用Task.IsCompleted检查您的任务是否已完成。
if (checkCFOPTask.IsCompleted && checkCFOPTask.Result)