Смотрите видео ниже, чтобы узнать, как установить наш сайт в качестве веб-приложения на домашнем экране.
Примечание: Эта возможность может быть недоступна в некоторых браузерах.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
что бы поток закрылся принудительно через определенный промежуток времени и вышел на BanEnd, надо поставить галочку и уставку времени.
и оптимизировать шаблон так, что бы он хоть иногда выходил на межкубовые линии, так как эта настройка работает только в тех местах.
в циклах c# надо вставлять такие конструкции
C#:
// выход по внешнему требованию
if(((ZennoLab.InterfacesLibrary.ProjectModel.Collections.IContextExt)project.Context).IsInterrupted) throw new Exception("Внешнее прерывание");
if(Global.Variables.IsProjectMaker && !Global.Variables.IsDebugMode) throw new Exception("Внешнее прерывание");
что бы поток закрылся принудительно через определенный промежуток времени и вышел на BanEnd, надо поставить галочку и уставку времени. Посмотреть вложение 70612
и оптимизировать шаблон так, что бы он хоть иногда выходил на межкубовые линии, так как эта настройка работает только в тех местах.
в циклах c# надо вставлять такие конструкции
C#:
// выход по внешнему требованию
if(((ZennoLab.InterfacesLibrary.ProjectModel.Collections.IContextExt)project.Context).IsInterrupted) throw new Exception("Внешнее прерывание");
if(Global.Variables.IsProjectMaker && !Global.Variables.IsDebugMode) throw new Exception("Внешнее прерывание");
Cпасибо за статью но воспользовался решением от Verbin.
thread.Interrupt() и все работает как нужно ( но только в зп).
П.С. по поводу таймаута зенновского то он работает 50/50 с чем это связанно я не знаю.
Ну а по поводу оптимизации проекта + проверкам в кубиках c#, то это все конечно хорошо но тут нужно было решение без переписывания 100 кубиков поэтому просто асинк таймер + жесткий стоп через метод указанный выше работают на ура.
// запускаем проверку в дочернем потоке с таймаутом в 5 секунд
project.Exit(5);
// имитируем долгое выполнение в течении 10 секунд
for (int counter = 0; counter < 10; counter++)
{
project.SendInfoToLog($"Поток: {Thread.CurrentThread.ManagedThreadId} Счетчик: {counter}", true);
Thread.Sleep(1000);
}
Класс в общем коде:
public static class ProjectExtensions
{
/// <summary>
/// Остановить выполнение проекта по таймауту
/// </summary>
public static void Exit(this IZennoPosterProjectModel project, int timeoutInSeconds)
{
Thread thread = Thread.CurrentThread;
System.Threading.Tasks.Task.Run(() =>
{
int counter = 0;
while (true)
{
Thread.Sleep(1000);
counter++;
if (counter > timeoutInSeconds)
{
project.SendInfoToLog($"Останавливаем поток по таймауту: {thread.ManagedThreadId}", true);
thread.Interrupt();
break;
}
}
});
}
}
Нет, ну круто, конечно, чё... И как раз ответ на вопрос, который меня долго мучил... Но только если основной поток завершаентся раньше фонового, вся зенка крэшится!
Вопрос в том, почему и как этого избежать? Крэшится на строке thread.Interrupt(); в общем коде.
Нет, ну круто, конечно, чё... И как раз ответ на вопрос, который меня долго мучил... Но только если основной поток завершаентся раньше фонового, вся зенка крэшится!
Вопрос в том, почему и как этого избежать? Крэшится на строке thread.Interrupt(); в общем коде.
Нет, ну круто, конечно, чё... И как раз ответ на вопрос, который меня долго мучил... Но только если основной поток завершаентся раньше фонового, вся зенка крэшится!
Вопрос в том, почему и как этого избежать? Крэшится на строке thread.Interrupt(); в общем коде.
Переработал и протестировал код.
Обновленное решение работает стабильно в ProjectMaker и ZennoPoster.
В общий код добавляем класс:
C#:
public class Timeout
{
private IZennoPosterProjectModel _project = null;
private int _timeoutInSeconds = 0;
private CancellationTokenSource _cancellationTokenSource = null;
public Timeout(IZennoPosterProjectModel project, int timeoutInSeconds)
{
_project = project;
_timeoutInSeconds = timeoutInSeconds;
_cancellationTokenSource = new CancellationTokenSource();
}
public void Start()
{
var thread = Thread.CurrentThread;
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
_project.SendInfoToLog($"Запускаем фоновый поток: {Thread.CurrentThread.ManagedThreadId}", true);
var endTime = DateTime.Now.AddSeconds(Convert.ToDouble(_timeoutInSeconds));
while (true)
{
Thread.Sleep(100);
if (_cancellationTokenSource.Token.IsCancellationRequested)
{
_project.SendInfoToLog($"Останавливаем фоновый поток: {Thread.CurrentThread.ManagedThreadId}", true);
break;
}
var currentTime = DateTime.Now;
if (currentTime >= endTime)
{
_project.SendInfoToLog($"Останавливаем основной поток: {thread.ManagedThreadId}", true);
_project.SendInfoToLog($"Останавливаем фоновый поток: {Thread.CurrentThread.ManagedThreadId}", true);
thread.Interrupt();
break;
}
}
}, _cancellationTokenSource.Token);
}
public void Stop()
{
_cancellationTokenSource.Cancel();
Thread.Sleep(1000);
}
}
Первый кубик в проекте для запуска фонового потока с проверкой по таймауту:
C#:
// запускаем проверку в фоновном потоке с таймаутом в 5 секунд
project.Context["timeout"] = new Timeout(project, 5);
(project.Context["timeout"] as Timeout).Start();
Второй кубик в проекте для имитации выполнения разных задач:
C#:
// имитируем долгое выполнение в течении 10 секунд
for (int counter = 0; counter < 10; counter++)
{
project.SendInfoToLog($"Поток: {Thread.CurrentThread.ManagedThreadId} Счетчик: {counter}", true);
Thread.Sleep(1000);
}
Кубик завершения проекта по Bad End и Good End для завершения фонового потока:
C#:
(project.Context["timeout"] as Timeout).Stop();
Прикрепил к сообщению тестовый проект, работает на версии 7.2 и выше.
Если вам пригодилось решение, достаточно нажать на кнопку Спасибо под сообщением.
позанудствую
после _cancellationTokenSource.Cancel(); я бы все же поставил небольшую паузу. хоть в параллельном потоке и стоит достаточно маленькая пауза в 100 мс. но разрыв все равно есть.
позанудствую
после _cancellationTokenSource.Cancel(); я бы все же поставил небольшую паузу. хоть в параллельном потоке и стоит достаточно маленькая пауза в 100 мс. но разрыв все равно есть.
Спасибо большое! Очень ценная информация. Я пока до совсем многопоточного программирования не вырос, так что придется сделать левел ап чтобы понять полностью. Но код рабочий, все супер! Вы таки мастер! )
Да, но он не вполне корректно работает, как оказалось. Немного не та цель выполняется.
Если действия описаны и выполняются в пределах этого одного кубика - все норм. Фоновый поток мониторит основной поток (жив ли он), ожидает немного (вместо ожидания можно прописать свои действия) прерывает его и завершается сам. Но как только действие шаблона переходит к выполнению других кубиков, прерывание основного потока не происходит. Вероятно потому, что при выполнении каждого последующего кубика создаётся новы поток. По крайней мере идентификатор потока (его номер) другой.
походу ты запутался в шаблонах, потоках и иже там
я тебя спрашивал про твой шаблон. ты говоришь что весь шаблон состоит из одного кубика, и тут же говоришь что на следующем кубике код не работает.
конечно он не работает, ты же вызываешь thread.Interrupt(); в том же кубике в котором и вызываешь запуск кода.
вот здесь https://zennolab.com/discussion/threads/ostanovka-potokov-iz-obschego-koda.87667/post-589411
все разложено как и что вызывать, как завершать. а твой вариант не имеет смысла совсем. ну может и имеет для контроля конкретного одного кубика, но ни как не относится к теме топика, а именно контролю всего проекта.
Переработал и протестировал код.
Обновленное решение работает стабильно в ProjectMaker и ZennoPoster.
В общий код добавляем класс:
C#:
public class Timeout
{
private IZennoPosterProjectModel _project = null;
private int _timeoutInSeconds = 0;
private CancellationTokenSource _cancellationTokenSource = null;
public Timeout(IZennoPosterProjectModel project, int timeoutInSeconds)
{
_project = project;
_timeoutInSeconds = timeoutInSeconds;
_cancellationTokenSource = new CancellationTokenSource();
}
public void Start()
{
var thread = Thread.CurrentThread;
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
_project.SendInfoToLog($"Запускаем фоновый поток: {Thread.CurrentThread.ManagedThreadId}", true);
var endTime = DateTime.Now.AddSeconds(Convert.ToDouble(_timeoutInSeconds));
while (true)
{
Thread.Sleep(100);
if (_cancellationTokenSource.Token.IsCancellationRequested)
{
_project.SendInfoToLog($"Останавливаем фоновый поток: {Thread.CurrentThread.ManagedThreadId}", true);
break;
}
var currentTime = DateTime.Now;
if (currentTime >= endTime)
{
_project.SendInfoToLog($"Останавливаем основной поток: {thread.ManagedThreadId}", true);
_project.SendInfoToLog($"Останавливаем фоновый поток: {Thread.CurrentThread.ManagedThreadId}", true);
thread.Interrupt();
break;
}
}
}, _cancellationTokenSource.Token);
}
public void Stop()
{
_cancellationTokenSource.Cancel();
Thread.Sleep(1000);
}
}
Первый кубик в проекте для запуска фонового потока с проверкой по таймауту:
C#:
// запускаем проверку в фоновном потоке с таймаутом в 5 секунд
project.Context["timeout"] = new Timeout(project, 5);
(project.Context["timeout"] as Timeout).Start();
Второй кубик в проекте для имитации выполнения разных задач:
C#:
// имитируем долгое выполнение в течении 10 секунд
for (int counter = 0; counter < 10; counter++)
{
project.SendInfoToLog($"Поток: {Thread.CurrentThread.ManagedThreadId} Счетчик: {counter}", true);
Thread.Sleep(1000);
}
Кубик завершения проекта по Bad End и Good End для завершения фонового потока:
C#:
(project.Context["timeout"] as Timeout).Stop();
Прикрепил к сообщению тестовый проект, работает на версии 7.2 и выше.
Если вам пригодилось решение, достаточно нажать на кнопку Спасибо под сообщением.