Вход

Просмотр полной версии : ФБ C# как организовать не блокирующую задержку внутри скрипта?



Igor V
22.03.2019, 10:48
Пытаюсь выполнить следующий код в ФБ, ожидаю что значения переменной на выходе будет меняться с интервалами времени в 2 сек. При выполнении значение на выходе постоянно одно - "2".
public partial class ФБ : ScriptBase
{
public override void Start()
{
Параметр1=1;
WaitNSeconds(2);
Параметр1=2;
WaitNSeconds(2);
}
private static void WaitNSeconds(int segundos)
{
if (segundos < 1) return;
DateTime _desired = DateTime.Now.AddSeconds(segundos);
while (DateTime.Now < _desired)
{
//System.Windows.Forms.Application.DoEvents();
}
}
}

SCADAMaster
22.03.2019, 11:08
Вы ерунду написали.
Во первых метод Start вызывается один раз при старте скады.
Во вторых нельзя вызывать такие бесконечные циклы.

Вам нужно сделать у ФБ периодический опрос, в методе Execute когда вы запускаете ваш таймер, прибавить к текущему времени нужное количество секунд и выйти из метода. В следующем заходе проверяете включен ли ваш таймер и не достигло ли текущее время заданного

Igor V
22.03.2019, 11:21
Вы ерунду написали.
Во первых метод Start вызывается один раз при старте скады.
Во вторых нельзя вызывать такие бесконечные циклы.

Вам нужно сделать у ФБ периодический опрос, в методе Execute когда вы запускаете ваш таймер, прибавить к текущему времени нужное количество секунд и выйти из метода. В следующем заходе проверяете включен ли ваш таймер и не достигло ли текущее время заданного

Возможно я не достаточно понятно обозначил проблему. Теперь пишем не ерунду:

public partial class ФБ : ScriptBase
{
static PreciseTimer timer = new PreciseTimer();
public override void Execute()// значения 1 2 1 2 1 2 с указанной задержкой
{
Параметр1=1;
timer.Wait(2*100*100*100);//Ждем 2 секунды
Параметр1=2;
timer.Wait(2*100*100*100);
}
}
public class PreciseTimer
{
IntPtr _timerHandle;

public PreciseTimer()
{
_timerHandle = CreateWaitableTimer(IntPtr.Zero, false, null);
}

public bool Wait(long microseconds)
{
// задаётся 100-наносекундными интервалами
long time = -microseconds * 10;
if (SetWaitableTimer(_timerHandle, ref time, 0, IntPtr.Zero, IntPtr.Zero, false))
{
int result = WaitForSingleObject(_timerHandle, INFINITE);
if (result == 0)
return true;
}
return false;
}

const uint INFINITE = 0xFFFFFFFF;

[DllImport("kernel32.dll")]
static extern IntPtr CreateWaitableTimer(IntPtr lpTimerAttributes,
bool bManualReset,
string lpTimerName);

[DllImport("kernel32.dll")]
static extern bool SetWaitableTimer(IntPtr hTimer,
ref long pDueTime,
int lPeriod,
IntPtr pfnCompletionRoutine,
IntPtr lpArgToCompletionRoutine,
bool fResume);

[DllImport("kernel32.dll")]
static extern int WaitForSingleObject(IntPtr handle, uint milliseconds);
}

В VS этот алгоритм отрабатывает. Мне нужны временные задержки, которые не будут блокировать выполнение основного потока.
Пока получаю такое сообщение : Зависание рабочего потока ID=10300 - Объект 1 : Выполнение Объект 1.Скрипт : Разрушительный сбой

SCADAMaster
22.03.2019, 12:12
Мы вам объяснили как сделать в прошлом сообщении
Периодический опрос у ФБ, и Execute сравниваете сохраненное время с текущим