0

Пытаюсь написать телеграм-бота не в консольном приложении, а в Window Forms. И столкнулся с проблемой. Я хочу, чтобы различные действия бота отображались в форме, если конкретно, то в RichTextBox. Но не получается это сделать, так действия происходят в статическом асинхронном методе. Как правильно поступить в этой ситуации? Прошу сильно не пинать - я начинающий и многого не знаю.

namespace TelegramBotTest
{
    public partial class Form1 : Form
    {
        private static ITelegramBotClient bot = new TelegramBotClient("TOKEN");
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        var cts = new CancellationTokenSource();
        var cancellationToken = cts.Token;
        var receiverOptions = new ReceiverOptions
        {
            AllowedUpdates = { }, // receive all update types
        };
        bot.StartReceiving(
            HandleUpdateAsync,
            HandleErrorAsync,
            receiverOptions,
            cancellationToken
        );
        WriteToRichBox(DateTime.Now + ": запущен бот " + bot.GetMeAsync().Result.FirstName);
    }

    private static void WriteToRichBox(string s)
    {
        richTextBox.AppendText(s + "\n"); //Здесь ошибка "Для нестатического поля, метода или свойства требуется ссылка на объект"
    }

    public static async Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
    {
        string st = Newtonsoft.Json.JsonConvert.SerializeObject(update);
        WriteToRichBox(st));
        if (update.Type == Telegram.Bot.Types.Enums.UpdateType.Message)
        {
            // Некоторые действия
        }
    }

    public static async Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken)
    {
        // Некоторые действия
        WriteToRichBox(Newtonsoft.Json.JsonConvert.SerializeObject(exception));
    }
}

}

Serzhik
  • 16

1 Answers1

0

Для записи не главного потока вы можете написать метод который будет писать в richTextBox. То есть выходим из потока и делаем запись в GUI

 public void Logger(string text)
        {
            richTextBox.Invoke((MethodInvoker)delegate
            {
                if (WriteToRichBox.Lines.Count() == 0)
                {
                    richTextBox.AppendText($"{text}");
                }
                else
                    richTextBox.AppendText($"\r\n{text}");
            });
        }

действия происходят в статическом асинхронном методе. Я бы удалил все статические методы и объекты. Так как в многопотоке если вы не обрабатываете, не блокируете данные для редактирования, в данных будет полная каша. Например в записи от 0 до 9 вы можете получить запись 0,1,2,2,2,2,2,2,2 и т.п

xellan
  • 560
  • 3
  • 11
  • string st = Newtonsoft.Json.JsonConvert.SerializeObject(update); WriteToRichBox(st)); Зачем вы десерилизуете объект update? Библиотека телеграмм сама десерилизует ответ в update. Вы ей можете сразу пользоваться как моделью. – xellan May 18 '23 at 12:23
  • bot.GetMeAsync().Result используйте await вместо Result так будет правильнее – xellan May 18 '23 at 12:25
  • 1
    "Я бы удалил все статические методы и объекты." Если я удаляю static в public static async Task HandleUpdateAsync, то бот перестаёт работать. – Serzhik May 18 '23 at 12:43
  • 1
    Зачем вы десерилизуете объект update? Библиотека телеграмм сама десерилизует ответ в update. - вот этого я не знал. Спасибо! – Serzhik May 18 '23 at 12:45
  • Lines.Count() == 0 это жутко неэффективный тормозной вызов, жрущщий кучу ресурсов – aepot May 18 '23 at 12:57
  • 1
    Спасибо! Ваши ответы полностью решили мой вопрос! public static async Task HandleUpdateAsync изменил на public static async Task HandleUpdateAsync и запись в richTextBox1 сделал по вашему совету: public void Logger(string text) { richTextBox1.Invoke((MethodInvoker)delegate { if (richTextBox1.Lines.Count() == 0) { richTextBox1.AppendText($"{text}"); } else richTextBox1.AppendText($"\r\n{text}"); }); } Всё работает! – Serzhik May 18 '23 at 12:58
  • @Serzhik вообще зачем RTB? Простой текстбокс используйте, он легче и быстрее работает. И вообще можно .AppendText(text + Environment.NewLine); без лишних фокусов и проверок – aepot May 18 '23 at 13:03
  • 2
    @aepot Действительно, текстбокс с полосой прокрутки точно так же работает. Изменил. И, да, в моем случае проверка на нулевое количество строк не нужна. Сделал по вашему совету. Спасибо! – Serzhik May 18 '23 at 13:24
  • @Serzhik еще там .ScrollToEnd(); вроде полезен будет. – aepot May 18 '23 at 13:25