Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
 Аватар для fufel
20 / 20 / 6
Регистрация: 28.02.2011
Сообщений: 535

Многопоточность в Windows Service

20.06.2018, 12:15. Показов 3905. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.
Дали задание переписать простую Windows Form в Windows Service.
Windows Form была заточена на то чтобы все события обрабатывались в главном UI потоке.
Для этих целей использовалось "InvokeRequired/BeginInvoke/Invoke".

В Windows Service нету UI, но переписывать логику будет крайне накладно.
Какие есть методы чтобы события из второстепенных потоков обрабатывались в главным потоке?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.06.2018, 12:15
Ответы с готовыми решениями:

Service для Windows
Доброго времени суток всем! У меня такой вопросик, вот решил написать для себя сервис для винды который снимает скриншоты экрана... ...

Windows service + WiX
Здравствуйте. Я создал проект Windows service с таким кодом: public partial class Service1 : ServiceBase { ...

Windows Service C#
Господа помогите.....мозг взорван курсовую завтра сдавать....Пытаюсь написать Windows Service на C# который при старте будет писать в файл...

25
Эксперт .NET
 Аватар для Usaga
14315 / 9401 / 1355
Регистрация: 21.01.2016
Сообщений: 35,453
20.06.2018, 13:13
Цитата Сообщение от fufel Посмотреть сообщение
В Windows Service нету UI, но переписывать логику будет крайне накладно.
Вы определитесь, переписывать или нет. Хотите Windows Forms переделать в виде службы, то переписывать придётся. Если накладно, то вы не хотите переделывать приложение. Тут одно из двух.
0
 Аватар для fufel
20 / 20 / 6
Регистрация: 28.02.2011
Сообщений: 535
20.06.2018, 13:30  [ТС]
Usaga, мне для начало надо понять как в Windows service из второстепенного потока вызвать событие которое будет обрабатываться в главном потоке. Я пока это найти не могу.
В Windows form было так, InvokeRequired проверяю, главный это поток или нет и если не главный то вызываю событие в главном потоке.
Как это реализовать?
0
Эксперт .NET
 Аватар для Usaga
14315 / 9401 / 1355
Регистрация: 21.01.2016
Сообщений: 35,453
20.06.2018, 13:36
fufel, а это надо? Я имею в виду, что диспетчеризация требовалась самой Windows при работе с UI. У служб нет UI, значит и диспетчеризация нафиг не нужна. Разве что, нужно следить, чтобы не было thread racing, но это проблема исключительно вашего кода, и она актуальна везде.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
20.06.2018, 13:52
fufel, потокобезопасные коллекции, средства синхронизации потоков, блокировка ресурсов. Всё это легко гуглится по запросам типа "C# синхронизация потоков".
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
20.06.2018, 14:36
Как-то странно, ведь инвокер на формах нужен исключительно для обращения к UI єлементам. Если вьі завязьівали на єто еще и логику синхронизации, то....

Цитата Сообщение от Usaga Посмотреть сообщение
это проблема исключительно вашего кода
p.s. Что хоть форма делала? Слала запросьі по таймауту?
0
 Аватар для fufel
20 / 20 / 6
Регистрация: 28.02.2011
Сообщений: 535
20.06.2018, 15:05  [ТС]
Wolfdp, aquaMakc, Usaga,
Сейчас попробую описать часть кода словами чтобы было ясно к чему всё это.
1) В отдельном потоке живёт TCPListener который принимает сетевые соединения. При приёме нового соединения генерирует событие которое передаётся главному (UI) потоку.
Главный потов обрабатывает новое соединение и создаёт TCPClient который запускается в новом потоке.
2) Когда TCPClient получает сообщение он генерирует событие которое передаётся главному потоку.

В результате, вся логика происходит в главном потоке и в результате чего мне не надо думать о целостности данных поскольку всё происходит в одном потоке. Форма принимала события от других потоков и выполняла все действия.

П.С. Почему я так делаю. На данный момент я знаю что когда событие на форме отработала (Скажем нажатие кнопки) то форма (Поток) не исчезает а ждёт других действий. В тоже время если создавать свой поток то после обработки поток закрывается. И как сделать так чтобы поток уходил в ожидание событие из другого потока я не знаю.

Добавлено через 9 минут
Цитата Сообщение от aquaMakc Посмотреть сообщение
fufel, потокобезопасные коллекции, средства синхронизации потоков, блокировка ресурсов. Всё это легко гуглится по запросам типа "C# синхронизация потоков".
Мой сервер рассчитан на 10 соединений, и чтобы сделать оптимальнее, я все события из других потоков перенаправлю в главный поток. В итоге мне не надо работать с "потокобезопасные коллекции, средства синхронизации потоков, блокировка ресурсов...". все эти методы я знаю но для 10 соединений всё слишком не практично.

Вопрос мой в том как в Windows service в втором потоке создать событие которое будет обрабатываться в главном потоке?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.06.2018, 15:06
Цитата Сообщение от fufel Посмотреть сообщение
как сделать так чтобы поток уходил в ожидание событие из другого потока я не знаю.
Есть такие классы - AutoResetEvent, ManualResetEvent.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
20.06.2018, 15:35
Цитата Сообщение от fufel Посмотреть сообщение
1) В отдельном потоке живёт TCPListener который принимает сетевые соединения. При приёме нового соединения генерирует событие которое передаётся главному (UI) потоку.
Главный потов обрабатывает новое соединение и создаёт TCPClient который запускается в новом потоке.
Здесь поподробней. Вы создаёте TCPClient в Form.Invoke? Или просто в обработчике события? Если первый случай - так делать не надо. Вот тут можно в общих чертах почитать почему и как делать лучше.
Цитата Сообщение от fufel Посмотреть сообщение
все эти методы я знаю но для 10 соединений всё слишком не практично
Поверьте мне - практично. Если сразу не заложиться на рост нагрузки, то во-первых, в последствии вы можете столкнуться со своими-же ограничениями, которые заставят переписать весь код. А во-вторых, лучше с самого начала приучать себя писать правильно.
0
Эксперт .NET
 Аватар для Usaga
14315 / 9401 / 1355
Регистрация: 21.01.2016
Сообщений: 35,453
20.06.2018, 16:21
Цитата Сообщение от fufel Посмотреть сообщение
1) В отдельном потоке живёт TCPListener который принимает сетевые соединения. При приёме нового соединения генерирует событие которое передаётся главному (UI) потоку.
Главный потов обрабатывает новое соединение и создаёт TCPClient который запускается в новом потоке.
2) Когда TCPClient получает сообщение он генерирует событие которое передаётся главному потоку.
Вот примерно такой вот ерунды я и ожидал... Не обижайтесь.

Вам не нужен никакой "главный поток". Запускайте прослушку порта в отдельном потоке, при получении нового соединения запускайте его обработку в новом потоке (берите из пула). Ни какой завязки на "главный поток" тут не нужно вообще.
0
 Аватар для fufel
20 / 20 / 6
Регистрация: 28.02.2011
Сообщений: 535
20.06.2018, 16:28  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
Здесь поподробней. Вы создаёте TCPClient в Form.Invoke? Или просто в обработчике события? Если первый случай - так делать не надо. Вот тут можно в общих чертах почитать почему и как делать лучше.
1) Цикл который крутится в отдельном потоке, и когда кто то пытается установить связь то генерируется событие.
2) Обработка события в главной форме. Главный поток создаёт нужный класс, подписывает события и командой "Klient.Start()" отправляет в путь (Данная команда создаёт другой поток в котором живёт данный созданный объект).
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 1
while (true)
{
    TcpClient TCPClient_TMP = Listener.AcceptTcpClient();
    TCP_AcceptTcpClientEvent?.Invoke(TCPClient_TMP); //Call event.
}
 
// 2
public void Listener_AcceptTcpClient(TcpClient client)
{
    C_TCP_Client_S Klient = new C_TCP_Client_S(client);
                         
    //Add events                           
    Klient.TCP_Client_ClientConnectingEvent += TCP_Client_ClientConnectingInvoke;
    Klient.TCP_Client_ClientDisconectEvent += TCP_Client_ClientDisconectInvoke;
    Klient.TCP_Client_MessIncomingEvent += TCP_Client_MessIncomingInvoke;
 
    Klient.Start(); //TCPClient started work.
}
Цитата Сообщение от aquaMakc Посмотреть сообщение
Поверьте мне - практично. Если сразу не заложиться на рост нагрузки, то во-первых, в последствии вы можете столкнуться со своими-же ограничениями, которые заставят переписать весь код. А во-вторых, лучше с самого начала приучать себя писать правильно.
Не просто верю а на своём опыте уже почувствовал что надо делать сразу всё правильно. Но эта тема для другого разговора.

А теперь по проблеме, вот пример кода. В скобках указанны ID потоков в которых они выполняются.
ID 10 - Главный поток.
ID 11 - Второстепенный поток.

Вопрос в том что как метод "private void XXX_Mehod(object sender, EventArgs e)" запустить не с 11 потока (именно в 11 потоке был вызвано событие) а чтобы обработка события вызванная в 11 потоке обработалось в 10 потоке?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using NS_Settings_V7;
using System.Threading;
 
namespace TBotEventService_V3
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
 
            Logs.Info($"ID: {Thread.CurrentThread.ManagedThreadId.ToString()}"); //ID: 10
         }
 
        #region Service Value's
        private static readonly log4net.ILog Logs = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
        #endregion
 
        protected override void OnStart(string[] args)
        {
            Logs.Info($"ID: {Thread.CurrentThread.ManagedThreadId.ToString()}");
            Logs.Info("Service: OnStart");
 
            MyEvent += XXX_Mehod;
 
            Thread myThread = new Thread(new ThreadStart(Count));
            myThread.Start(); // запускаем поток
        }
 
        private void XXX_Mehod(object sender, EventArgs e)
        {
            Logs.Info($"XXX_Mehod: {Thread.CurrentThread.ManagedThreadId.ToString()}"); //ID: 11
        }
 
        protected override void OnStop()
        {
            Logs.Info($"ID: {Thread.CurrentThread.ManagedThreadId.ToString()}");//ID: 10
            Logs.Info("Service: OnStop");
        }
 
        public event EventHandler MyEvent;
 
        public void Count() //Второй поток
        {
            for (int i = 1; i < 9; i++)
            {
                MyEvent?.Invoke(this, EventArgs.Empty);
 
                Logs.Info($"ID TH: {Thread.CurrentThread.ManagedThreadId.ToString()}"); //ID: 11
                Thread.Sleep(400);
            }
        }
    }
}
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
20.06.2018, 16:36
Цитата Сообщение от fufel Посмотреть сообщение
Цикл который крутится в отдельном потоке, и когда кто то пытается установить связь то генерируется событие
Обратите внимание на BeginAcceptTcpClient.

Цитата Сообщение от fufel Посмотреть сообщение
Klient.Start()
Client же.

Цитата Сообщение от fufel Посмотреть сообщение
TCP_AcceptTcpClientEvent?.Invoke(TCPClie nt_TMP);
Где и как обрабатывается это событие?

Цитата Сообщение от fufel Посмотреть сообщение
Вопрос в том что как метод "private void XXX_Mehod(object sender, EventArgs e)" запустить не с 11 потока (именно в 11 потоке был вызвано событие) а чтобы обработка события вызванная в 11 потоке обработалось в 10 потоке?
Зачем? Лично я не вижу такой необходимости.
0
 Аватар для fufel
20 / 20 / 6
Регистрация: 28.02.2011
Сообщений: 535
20.06.2018, 16:37  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
Вот примерно такой вот ерунды я и ожидал... Не обижайтесь.
Вам не нужен никакой "главный поток". Запускайте прослушку порта в отдельном потоке, при получении нового соединения запускайте его обработку в новом потоке (берите из пула). Ни какой завязки на "главный поток" тут не нужно вообще.
Не обижаюсь, я сам прекрасно понимаю что пишу через зад но что есть то есть (почему так вышло тема для другого топика, но пока задача стоит такая и с вашей помощи пытаюсь её решить).

Пока вопрос в том как мне из других потоков (их может быть 10) генерировать события так чтобы обработка всех событий происходила исключительно в одном и том же потоке?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,575
20.06.2018, 16:48
Цитата Сообщение от fufel Посмотреть сообщение
Пока вопрос в том как мне из других потоков (их может быть 10) генерировать события так чтобы обработка всех событий происходила исключительно в одном и том же потоке?
Зачем? Проще сделать синхронизацию.
0
 Аватар для fufel
20 / 20 / 6
Регистрация: 28.02.2011
Сообщений: 535
20.06.2018, 17:16  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
Обратите внимание на BeginAcceptTcpClient.
Также как и прошлая ссылка на тему "как не надо делать" поставил на заметку, буду читать (в том топике сходу нашел то что я не так делаю но это уже из другой темы).

Цитата Сообщение от aquaMakc Посмотреть сообщение
Client же.
Klient это ошибка которой уже 2 года. Но пока не исправляю

Цитата Сообщение от aquaMakc Посмотреть сообщение
Где и как обрабатывается это событие?
Вот полный код с проекта.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Class  TCP_Listener_S.cs
public delegate void TCP_AcceptTcpClientDelegate(TcpClient Klient);
public event TCP_AcceptTcpClientDelegate TCP_AcceptTcpClientEvent;
 
while (true)
{
    TcpClient TCPClient_TMP = Listener.AcceptTcpClient();
    TCP_AcceptTcpClientEvent?.Invoke(TCPClient_TMP); //Call event.
}
 
// Form.cs
TCP_Listener_S.TCP_AcceptTcpClientEvent += Listener_AcceptTcpClientInvoke; //New client accept
 
//Стандартная проверка на потоки
public void Listener_AcceptTcpClientInvoke(TcpClient client)
{
    if (InvokeRequired)
    {
        this.BeginInvoke(new C_TCP_Listener_S.TCP_AcceptTcpClientDelegate(this.Listener_AcceptTcpClient), client);
    }
    else
    {
        Listener_AcceptTcpClient(client);
    }
}
 
//Обработка события.
public void Listener_AcceptTcpClient(TcpClient client)
{
    C_TCP_Client_S Klient = new C_TCP_Client_S(client);
                         
    //Add events                           
    Klient.TCP_Client_ClientConnectingEvent += TCP_Client_ClientConnectingInvoke;
    Klient.TCP_Client_ClientDisconectEvent += TCP_Client_ClientDisconectInvoke;
    Klient.TCP_Client_MessIncomingEvent += TCP_Client_MessIncomingInvoke;
 
    Klient.Start(); //TCPClient started work.
}
Цитата Сообщение от aquaMakc Посмотреть сообщение
Зачем? Лично я не вижу такой необходимости.
Запрос может обрабатываться до 10 секунд. И чтобы не было проблем с целостностью данных я сделал так что все запросы уходят на один поток а этот самый поток по очереди обрабатывает все запросы.
П.С. я знаю что делаю не правильно, но это мой первый большой проект. И в нём я сделал большое количество ошибок. Не судите строго. Просто помогите мне.

Сейчас спустя полтора года я уже понял что такой потокобезопасные коллекции/Lock/семафоры. Но тогда когда всё начинал изучать я про события не чего не знал и про отдельные потоки. И про унаследование классов тоже не знал. Но нельзя сесть за C# и начать с ходу писать всё как надо. Всё изучал на коленках, всё познавал при помощи проб и ошибок. И то что вышло (Криво, боко, страшно с точки зрения программирование) работает и работает хорошо. Просто надо переделать на Windows Server а не переписывать всё с нуля по всем догмам программирования чтобы потом опять понять что всё что я писал опять не правильною.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
20.06.2018, 17:26
Цитата Сообщение от fufel Посмотреть сообщение
Klient это ошибка которой уже 2 года. Но пока не исправляю
Ставим курсор, ПКМ -> Переименовать... или 2 раза подряд CTRL+R. Переименование происходит сразу по всему пространству имён.

Цитата Сообщение от fufel Посмотреть сообщение
Вот полный код с проекта.
Вот так делать не надо.

Цитата Сообщение от fufel Посмотреть сообщение
Просто надо переделать на Windows Server а не переписывать всё с нуля по всем догмам программирования чтобы потом опять понять что всё что я писал опять не правильною.
У тебя прекрасный шанс всё переделать. Исправить архитектуру. Улучшить код фундамента. При этом научиться чему-то действительно полезному. Не надо такие моменты упускать. Это очень редкий зверь. Гораздо чаще в работе программиста приходится ковыряться в тоннах шлака, написанного N-лет назад без возможности переделать, т.к. на это не выделяется время.
0
Эксперт JS
6497 / 3908 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
20.06.2018, 17:26
Сейчас спустя полтора года я уже понял что такой потокобезопасные коллекции/Lock/семафоры.
fufel, а про то, что в асинхронном коде нельзя использовать Mutex/Monitor/lock, уже знаете?

За lock уже сам компилятор бьёт по шаловливым ручкам, а с Mutex и Monitor уже возможны интересные приключения ))


Как раз пишет Stephen Cleary, человек и пароход:
https://msdn.microsoft.com/mag... 2147217396
0
 Аватар для fufel
20 / 20 / 6
Регистрация: 28.02.2011
Сообщений: 535
20.06.2018, 18:41  [ТС]
Ладно ребята, всем спасибо за уделённое ваше внимание. И так помогли )))
Буду читать те ссылки которые вы дали, и буду дальше решать свою задачу.

Цитата Сообщение от aquaMakc Посмотреть сообщение
Вот так делать не надо.
Не в обиду но в основном так и говорят что "Вот так делать не над/Так не надо", но как делать надо (пример код) не дают.
Если посмотриш на картинку то там выходит такое дело.
Есть центр, он центра надо сделать 4 шага чтобы попасть в обведённую кругом точку.
Черный цвет это твой решение, оно идеально, оно превосходно. Я сделал так как я смог (Зелёный цвет). Затратил больше шагов, с самого начала сделал первый шаг совсем в другую сторону но я смог дойти до нужной точки, и хоть через зад но всё прекрасно работает. Но показав своё решение я получаю выше стоящий ответ.
И что мне теперь делать? всё откатывать назад и пытатся найти другой (более вернее путь)? так я могу сделать три попытки (Желтый цвет) и все попытки уйдут в молоко. И что мне остаётся делать? Так как я сделал (работает) но это очень плохо, а как надо негде взять.
Это относится и к второму комментарию, я прекрасно понимаю что делаю через з*д но нету у меня во круге тех кто может мне сказать как надо делать. Есть google, вы и моя задача.

amr-now, намотал на ус, почитаю и попробую сделать правильные выводы (не шагнув на желтую линию), и буду дальше решать свою задачу.
Изображения
 
0
Эксперт JS
6497 / 3908 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
20.06.2018, 19:12
fufel, ну тут уж насколько позволит здоровье.

Тему concurrency не бросайте. Она сейчас новая и модная. Даже устоявшегося перевода не имеет.

Concurrency - одновременное или псевдоодновременное выполнение различных частей программного кода; или одного кода для разных данных. Является обобщенным понятием для параллельного, многопоточного, асинхронного программирования.

Как теория действует и для C#, и для Java, и для JavaScript. Так что в любом случае тему надо знать.

Вьётся вокруг страшных слов Rx, Promise и тд.


-----
Так что на одних Invoke() свет клином не сошелся ))
0
Эксперт .NET
 Аватар для Usaga
14315 / 9401 / 1355
Регистрация: 21.01.2016
Сообщений: 35,453
20.06.2018, 19:41
fufel, хороший совет "как надо" начинается с полного описания задачи и мотивации, которая привела к вопросу. Вникать и расписывать решение вопроса, который уже изначально было понятно, что решает кривую задачу (привязки к "главному потоку" в службе, где это не играет роли) - дело бесполезное. Поэтому всё и свелось к фразам "так вообще не делается" и "это фигня и через зад".

Собственно, вам озвучили, что вы ищете решение несуществующей проблемы. XY problem. Так, что диаграмма выше как-то тут не вяжется. Уж извините.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.06.2018, 19:41
Помогаю со студенческими работами здесь

Сервер на Windows service
Мне нужно сделать сервер как службу windows,т.е. сделать его как проект windows service..может кто нибудь подкинет для начала пример...

A Windows service with the name MySQL already exists. Please uninstall this service correctly or choose a different name for the new service.
Не знаю что делать дальше

Windows Service Manager Tray , Windows Service Manager (SrvMan) информация
Есть ли у кого то информация по Windows Service Manager Tray , Windows Service Manager (SrvMan) . Статьи , описания , инструкции по...

Как переделать Windows Forms приложение в Windows Service с UI?
Здравствуйте, уважаемые посетители форума! Вопрос такой. У меня есть приложение C# Win Forms с интерфейсом. Как из него сделать...

Оболочка BASH в Windows (Windows Service for Linux)
Информация, которую можно получить по состоянию на текущий момент, заставляет отнестись серьёзно к возможности появления новой командной...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru