settimeout - Как реализовать таймаут на C#?


0

Доброго времени суток всем читающим!

Помогите, пожалуйста, реализовать таймаут на C#.

Занимаюсь задачей автоматизации десктопного приложения с помощью фреймворка Winium.Cruciatus и требуется установить таймаут на поиск элемента приложения, то есть поиск элемента должен выполняться в пределах заданного времени и, в случае, если элемент за это время не будет найден должна формироваться ошибка, которую я потом смогу обработать.

Вот код поиска элемента, на который необходимо установить таймаут:

var OpenShift = CashierWindow.FindElementByname("Да");
{
    try
    {
        OpenShift.Click();
        CashierWindow.FindElementByUid("6").Click();
        CashierWindow.FindElementByUid("6").Click();
    }
    catch
    {
        Console.WriteLine("...");
    }
}
Источник
  •  120
  •  4
  • 21 янв 2019 2019-01-21 05:24:01

4 ответа

0

Всем большое спасибо!

Большое спасибо! Натолкнули меня на идею реализации таймаута через запуск асинхронной операции.

Вот какая утилита получилась:

using System;
using System.Threading.Tasks;
using Winium.Cruciatus.Core;
using Winium.Cruciatus.Elements;
using Winium.Cruciatus;


static class IfExistsClass
{
    public static CruciatusElement GetIfExists(By element, CruciatusElement root, double timeout = 90000)

    {

        var StartDateTime = DateTime.Now;

        CruciatusFactory.Settings.SearchTimeout = (int)timeout;

        while ((DateTime.Now - StartDateTime).TotalMilliseconds < timeout) ;

        {
            var FindElement = Task<CruciatusElement>.Run(() =>


            {
                var elementFound = root.FindElement(element);
                return elementFound;


            });

            if (FindElement.Wait(TimeSpan.FromMilliseconds(30000)))
                return FindElement.Result;

            else

                Console.WriteLine("Timeout поиска элемента");


        }

        return null;

    }
}
  • 23 янв 2019 2019-01-23 19:24:35
-1
    static void Main(string[] args)
            {
                SetTimeout(2000, () => Console.WriteLine("2"));
                Console.WriteLine("1");
                Console.ReadKey();
            }

            static void SetTimeout(int delayMiliSeconds, Action action)
            {
                Task.Factory.StartNew(() =>
                {
                    Thread.Sleep(delayMiliSeconds);
                    action.Invoke();


                });
             }

Еще setinterval

static void SetInterval(int delayMiliSeconds, Action action)
        {
            void Repeat()
            {
                var T = Task.Factory.StartNew(() =>
                {
                    Thread.Sleep(delayMiliSeconds);
                    action.Invoke();
                    Repeat();
                });
            }
            Repeat();
        }
Нашел, кстати, решение через таски. Можно так: var task = Task.Run(action); (task.Wait(TimeSpan.FromMilliseconds(30000))); — 23 янв 20192019-01-23 08:35:06.000000
Andrew, Вы совершенно правы. В Winium.Cruciatus я нашел только свойство SearchTimeout, но это свойство служит, как я понимаю, для задания интервала между событиями. Вот в этом примере реализован таймаут с помощью SearchTimeout: gist.github.com/bangonkali/5c46a143e866905c4487. Но как Вы верно отметили - это решение не прерывает поис элемента после заданного времени, то есть у меня по-прежнему повисает тест на поиске элемента. — 23 янв 20192019-01-23 08:32:06.000000
И как это спасет от зашитого таймаута внутри Winium? Вот он выставлен на 60 секунд по дэфолту.... Что даст твой код в таком случае? Он же не отменит поиск элемента который уже будет осуществлятся самим Winium-ом. — 22 янв 20192019-01-22 08:03:31.000000
-1

Универсальный таймаут с использованием тасков:

    public void TryFlush()
    {
        int FlushTimeOut = 11;
        Task flushingTask = Task.Factory.StartNew(() => Flushing());
        var timeoutMilliseconds = FlushTimeOut * 1000;
        var isCompleted = flushingTask.Wait(timeoutMilliseconds);

        if (!isCompleted)
            throw new TimeoutException($"Время ожидания истекло(default {FlushTimeOut} seconds)");

         Console.WriteLine("Flushed");
    }

    private void Flushing()
    {
        //ваша долгая задача
        Thread.Sleep(10000);
        Console.WriteLine("Flushing done"); 
    }
В даном случае нужно смотреть на сам вопрос а не на заголовок. В даном случае юай не важен, а важно то, что реализация через доп.таймаут не отменяет внутренних таймаутов Winium-а. Напомню, что именно через него и автоматизируются тесты в случае ТС. — 22 янв 20192019-01-22 10:15:20.000000
Посмотрите на заголовок вопроса, посмотрите на теги. Автор может реализовать таймаут на слое бизнес логики, а UI может меняться — 22 янв 20192019-01-22 09:57:48.000000
И как это спасет от зашитого таймаута внутри Winium? Вот он выставлен на 60 секунд по дэфолту.... Что даст твой код в таком случае? Он же не отменит поиск элемента который уже будет осуществлятся самим Winium-ом. — 22 янв 20192019-01-22 08:03:17.000000
1

У Winium есть внутренний таймаут на поиск элемента.

Копать нужно в сторону Implicit и Explicit Waits и пробовать изменять их(предварительно почитав для чего каждый из них).

Т.к. они существуют УЖЕ (а они существуют, судя по https://github.com/2gis/Winium.Desktop/issues/227 ), то своя реализация своего отдельного таймаута будет ошибочным подходом.

  • 21 янв 2019 2019-01-21 05:41:58