Зависание потока C# без ошибок (потенциально - буфер обмена)

Romanuss

Client
Регистрация
15.03.2014
Сообщения
40
Благодарностей
6
Баллы
8
Всем привет.
Долго бьюсь, но никак не могу победить и даже не понимаю в чем проблема-то.
Поток зависает на определенном действии, без ошибок, просто C# висит и всё, всё время в одном месте, предположил, что связано с буфером обмена.

Фрагмент экшена, где случается зависание:
project.SendInfoToLog("Пробуем вставку через буфер обмена", true);
try
    {       
        // Выполняем вставку
        bool success = ZennoLab.OwnCode.CommonCode.ClipboardTools.SafePasteText(instance, project, domains);
        project.SendInfoToLog("Вставил домены из буфера обмена", true);
        
        if(!success)
        {
            project.SendErrorToLog("Не удалось вставить домены", true);
            throw new Exception("Не смог вставить домены");
        }
        
        project.SendInfoToLog("Буфер обмена - всё окей", true);
        return "OK";
    }
    catch (Exception ex)
    {
        project.SendInfoToLog($"Буфер обмена ошибка: {ex.Message}", true);
        
        // Если было много доменов и буфер не сработал - пробуем построчную вставку
        if (domainCount >= 5)
        {
            project.SendInfoToLog("Буфер обмена не сработал, пробуем построчную вставку как fallback", true);
            
            try
            {
                targetElement.Click();
                System.Threading.Thread.Sleep(100);
                
                // Вставляем построчно с Enter между ними
                for (int i = 0; i < domainLines.Length; i++)
                {
                    string domain = domainLines[i].Trim();
                    if (!string.IsNullOrEmpty(domain))
                    {
                        instance.SendText(domain, 0);
                        
                        if (i < domainLines.Length - 1)
                        {
                            instance.SendText("{ENTER}", 0);
                        }
                    }
                }
                
                project.SendInfoToLog("Fallback построчная вставка выполнена", true);
                return "OK";
            }
            catch (Exception ex2)
            {
                project.SendInfoToLog($"Fallback построчная вставка ошибка: {ex2.Message}", true);
            }
        }
    }
А вот класс, в котором идет копирование и вставка из буфера обмена, а потом возврат буфера (смотрел посты Альфреда, оттуда и взял логику)
Код:
public static class ClipboardTools
{
    private const int MAX_CLIPBOARD_RETRIES = 3;
    private const int CLIPBOARD_DELAY = 100;
    private const int PASTE_DELAY = 200;
    
    public static bool SafePasteText(Instance instance, IZennoPosterProjectModel project, string text)
    {
        lock(SyncObjects.InputSyncer)
        {
            try
            {
                // Проверяем входной текст
                if (string.IsNullOrEmpty(text))
                {
                    project.SendWarningToLog("Текст для вставки пуст", true);
                    return false;
                }

                var textbox = instance.ActiveTab.FindElementByXPath("//div[@role = 'textbox']", 0);
                if(textbox.IsNull)
                {
                    project.SendWarningToLog("Не найдено текстовое поле", true);
                    return false;
                }

                // Сохраняем предыдущее состояние буфера с повторами
                string previousText = GetClipboardTextSafely(project);
                
                try
                {
                    // Подготавливаем элемент для ввода
                    textbox.Click();
                    Thread.Sleep(50);
                    
                    // Устанавливаем текст в буфер с повторами
                    bool clipboardSet = SetClipboardTextSafely(text, project);
                    if (!clipboardSet)
                    {
                        project.SendErrorToLog("Не удалось установить текст в буфер обмена", true);
                        return false;
                    }

                    // Выполняем вставку с проверкой
                    bool pasteSuccess = ExecutePasteSafely(instance, project);
                    if (!pasteSuccess)
                    {
                        project.SendErrorToLog("Не удалось выполнить вставку", true);
                        return false;
                    }

                    Thread.Sleep(PASTE_DELAY);
                    return true;
                }
                finally
                {
                    // Восстанавливаем предыдущее состояние буфера
                    RestoreClipboardSafely(previousText, project);
                }
            }
            catch (Exception ex)
            {
                project.SendErrorToLog($"Критическая ошибка при вставке текста: {ex.Message}", true);
                return false;
            }
        }
    }

    private static string GetClipboardTextSafely(IZennoPosterProjectModel project)
    {
        for (int attempt = 1; attempt <= MAX_CLIPBOARD_RETRIES; attempt++)
        {
            try
            {
                if (System.Windows.Forms.Clipboard.ContainsText())
                {
                    return System.Windows.Forms.Clipboard.GetText();
                }
                return string.Empty;
            }
            catch (Exception ex)
            {
                project.SendWarningToLog($"Попытка {attempt} получения буфера неудачна: {ex.Message}", false);
                if (attempt < MAX_CLIPBOARD_RETRIES)
                {
                    Thread.Sleep(CLIPBOARD_DELAY);
                }
            }
        }
        
        project.SendWarningToLog("Не удалось получить содержимое буфера после всех попыток", false);
        return string.Empty;
    }

    private static bool SetClipboardTextSafely(string text, IZennoPosterProjectModel project)
    {
        for (int attempt = 1; attempt <= MAX_CLIPBOARD_RETRIES; attempt++)
        {
            try
            {
                // Сначала очищаем буфер
                System.Windows.Forms.Clipboard.Clear();
                Thread.Sleep(50);
                
                // Устанавливаем новый текст
                System.Windows.Forms.Clipboard.SetText(text, System.Windows.Forms.TextDataFormat.UnicodeText);
                Thread.Sleep(CLIPBOARD_DELAY);
                
                // Проверяем, что текст действительно установлен
                string clipboardContent = System.Windows.Forms.Clipboard.GetText();
                if (clipboardContent == text)
                {
                    return true;
                }
                else
                {
                    project.SendWarningToLog($"Попытка {attempt}: текст в буфере не соответствует ожидаемому", false);
                }
            }
            catch (Exception ex)
            {
                project.SendWarningToLog($"Попытка {attempt} установки буфера неудачна: {ex.Message}", false);
            }
            
            if (attempt < MAX_CLIPBOARD_RETRIES)
            {
                Thread.Sleep(CLIPBOARD_DELAY);
            }
        }
        
        return false;
    }

    private static bool ExecutePasteSafely(Instance instance, IZennoPosterProjectModel project)
    {
        for (int attempt = 1; attempt <= MAX_CLIPBOARD_RETRIES; attempt++)
        {
            try
            {
                // Выполняем вставку
                instance.ActiveTab.KeyEvent("v", "press", "ctrl");
                Thread.Sleep(PASTE_DELAY);
                
                // Можно добавить дополнительную проверку успешности вставки
                // например, проверить изменилось ли содержимое поля
                
                return true;
            }
            catch (Exception ex)
            {
                project.SendWarningToLog($"Попытка {attempt} вставки неудачна: {ex.Message}", false);
                if (attempt < MAX_CLIPBOARD_RETRIES)
                {
                    Thread.Sleep(CLIPBOARD_DELAY);
                }
            }
        }
        
        return false;
    }

    private static void RestoreClipboardSafely(string previousText, IZennoPosterProjectModel project)
    {
        for (int attempt = 1; attempt <= MAX_CLIPBOARD_RETRIES; attempt++)
        {
            try
            {
                System.Windows.Forms.Clipboard.Clear();
                Thread.Sleep(50);
                
                if (!string.IsNullOrEmpty(previousText))
                {
                    System.Windows.Forms.Clipboard.SetText(previousText, System.Windows.Forms.TextDataFormat.UnicodeText);
                }
                
                break; // Если успешно - выходим
            }
            catch (Exception ex)
            {
                project.SendWarningToLog($"Попытка {attempt} восстановления буфера неудачна: {ex.Message}", false);
                if (attempt < MAX_CLIPBOARD_RETRIES)
                {
                    Thread.Sleep(CLIPBOARD_DELAY);
                }
            }
        }
    }

    // Дополнительная функция для проверки состояния буфера
    public static bool IsClipboardReady()
    {
        try
        {
            return System.Windows.Forms.Clipboard.ContainsText() ||
                   System.Windows.Forms.Clipboard.ContainsData(System.Windows.Forms.DataFormats.Text);
        }
        catch
        {
            return false;
        }
    }
}
И ладно бы он хоть что-то выбивал, а так лог висит на "Пробуем вставку через буфер обмена" и всё, если посмотреть глазами - скрипт просто смотрит в окно ввода и всё. Окно неизменно, он 100% его находит. И отловить закономерность, когда появляется проблема не удалось, т.к. достаточно перезапустить программу и всё будет норм, иногда на пару минут, иногда на пару часов, иногда на целый день.

Помогите плз понять, хотя бы вектор :-)
 
Регистрация
05.04.2025
Сообщения
66
Благодарностей
19
Баллы
8
Добавьте побольше сообщений в лог, не только при ошибках.
 

Romanuss

Client
Регистрация
15.03.2014
Сообщения
40
Благодарностей
6
Баллы
8
Регистрация
05.04.2025
Сообщения
66
Благодарностей
19
Баллы
8

Romanuss

Client
Регистрация
15.03.2014
Сообщения
40
Благодарностей
6
Баллы
8
Регистрация
05.04.2025
Сообщения
66
Благодарностей
19
Баллы
8
"Пробуем вставку через буфер обмена" это последнее.
Ощущение, что что-то с буфером, но хз что и почему.
значит выполнение попало на
bool success = ZennoLab.OwnCode.CommonCode.ClipboardTools.SafePasteText(instance, project, domains);
добавьте вывод в лог в SafePasteText для каждого действия, а не только для ошибок.
а так же в каждой подфункции, которая вызывается из SafePasteText
 

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)