任务无法超时

时间:2017-03-28 12:24:19

标签: c# .net task-parallel-library

我使用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.

2 个答案:

答案 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)