powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Проблема с вызовом await Invoke из другого класса
22 сообщений из 22, страница 1 из 1
Проблема с вызовом await Invoke из другого класса
    #40007270
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.

Есть основная форма, которая запускается через:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
static class Program
{
	[STAThread]
	static void Main()
	{
		Application.EnableVisualStyles();
		Application.SetCompatibleTextRenderingDefault(false);
		Application.Run(new Form1());
	}
}



В Form1:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public HubConnection connection;
public IHubProxy hubProxy;

public async void Connect()
{
	connection = new HubConnection("адрес");
	hubProxy = connection.CreateHubProxy("название объекта");
	hubProxy.On<object>("название метода", (data) =>
		Invoke((Action)(() =>
		{
				MessageBox.Show("OK");
		}
	)));

	await connection.Start();

	Auth();
}

private async void Auth()
{
	await connection.Invoke("название метода", объект Credentials);
}



Если в Form1 сделать вызов Connect(), то увидим сообщение "OK".

Создаем класс, чтобы убрать в него весь этот код:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public class Class1 : Form
{
	... переменные

	public Class1()
	{
			Connect();
	}

	...методы
}



В From1 делаем Class1 a = new Class1() и не видим сообщения "OK".
await connection.Invoke("название метода", объект Credentials); не приводит к срабатыванию hubProxy.On<object>("название метода", (data).

Можно ли как-нибудь вызвать выполнение кода из другого класса, чтобы он работал также, как в основном?
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007275
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Опуская тот момент, что от этого кода кровь идет из глаз, но допустим он тестовый...

Зачем тут используется Invoke()? Возможно для формы, которая не показана на экране, Invoke и не должен срабатывать. Почему напрямую не вызвать MessageBox.Show?
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007278
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код тестовый.)

Суть в том, что есть сторонняя библиотека, с которой идет работа именно так, если верить документации.
Объявляем hubProxy.On<object>("название метода", (data), а потом вызываем метод с await connection.Invoke("название метода", объект Credentials); внутри.

При этом обработчик внутри hubProxy.On должен отрабатывать.
MessageBox.Show добавлен для отладки, т.к. смотреть в консоли или на контролах не очень удобно.

Если бы в другом классе все работало также, то можно было бы не обращать внимания на структуру вызовов, но не работает.
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007281
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я не про connection.Invoke а про Form.Invoke
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007283
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как правильно сделать, чтобы вызовы работали в любом классе?
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007284
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя может дело не в Invoke (хотя все равно его надо убрать и убрать наследование от Form), а в этом
Андрей Il
В From1 делаем Class1 a = new Class1()
Если a - локальная переменная, то сборщик мусора может успевать убить экземпляр Class1 до того, как он отработает.

Андрей Il
Код тестовый.)
Даже для тестового кода не надо говнокодить синхронный вызов асинхронных методов, да еще в конструкторе. Сделай нормальные асинхронные методы и вызывай с await-ом и не будет проблем.
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007285
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Il
Как правильно сделать, чтобы вызовы работали в любом классе?
ожидать окончания асинхронных вызовов с помощью await
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007317
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В Form1 переменная a для Class1 глобальная.
Внес изменения в вызов:
Код: c#
1.
2.
a = new Class1()
await a.Connect();



Class1:
Убрал public LibArgus() и изменил:
Код: c#
1.
2.
3.
4.
5.
6.
public async Task Connect()
...
	await oHubConnection.Start();
	await Auth();

private async Task Auth()



Делал по примерам, но все равно не работает.

Если сделать Class1 объявлением public partial class Form1 : Form, то все отрабатывает, т.к. фактически это один класс.

Интересует вариант именно с разными классами.
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007340
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Il
Внес
Андрей Il
Убрал
Андрей Il
изменил
Я не буду собирать это из непонятных кусков, покажи код, который получился (класс формы и Class1)
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007403
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Form1:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
namespace Form1
{
    public partial class Form1 : Form
    {
        public Class1 class1;

        public Form1()
        {
            InitializeComponent();
        }

        private async void Form1_Load(object sender, EventArgs e)
        {
            class1 = new Class1();
            await class1.Connect();
        }
    }
}



Class1:
Код: 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.
namespace Form1
{
    public class Class1 : Form
    {
        public HubConnection connection;
        public IHubProxy hubProxy;

        public async Task Connect()
        {
            connection = new HubConnection("адрес");
            hubProxy = connection.CreateHubProxy("название объекта");
            hubProxy.On<object>("название метода", (data) =>
                Invoke((Action)(() =>
                {
                    MessageBox.Show("OK");
                }
            )));

            await connection.Start();

            await Auth();
        }

        private async Task Auth()
        {
            await hubProxy.Invoke("название метода", объект Credentials);
        }
    }
}
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007407
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще раз. Убери Form.Invoke и наследование Class1 от Form
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007409
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы еще для чистоты эксперимента сделал вызов не в Form1_Load, а по кнопке, потому что в изначальном коде метод Connect, как я понимаю, тоже вызывается не из Form1_Load
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007418
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro
Еще раз. Убери Form.Invoke и наследование Class1 от Form

Если убрать наследование от Form, то не работает Invoke в hubProxy.On<object>("...", (data) =>
А как по-другому сделать обработку, пока не разобрался.

Shocker.Pro
Я бы еще для чистоты эксперимента сделал вызов не в Form1_Load, а по кнопке, потому что в изначальном коде метод Connect, как я понимаю, тоже вызывается не из Form1_Load

Вызов из Form1_Load, но кнопку добавил.
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007422
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так работает:
Код: c#
1.
2.
3.
hubProxy.On<object>("...", (data) =>
	MessageBox.Show("OK")
);


но является ли это правильным вариантом?
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007433
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Il
Так работает:
я с самого начала предложил его убрать. Ну хоть код немножко причесали.
Андрей Il
но является ли это правильным вариантом?
Что именно тебя смущает? MessageBox статический и, кажется, потокобезопасный класс
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007435
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Меня смущает то, что внутри блока hubProxy.On<object>("...", (data) => я не могу менять контролы Form1.
В коде обратиться могу, но при смене свойства, например, "Text" код прекращает выполняться с этой строки, но ошибки не возникает.
Если в режиме отладки нажать F10 на строке ...Text = "111", то в переменных будет:
"Недопустимая операция в нескольких потоках: попытка доступа к элементу управления '...' не из того потока, в котором он был создан."

С этим пока разбираюсь, а в остальном вариант рабочий.
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007436
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Il
Меня смущает то, что внутри блока hubProxy.On<object>("...", (data) => я не могу менять контролы Form1.
Ну так я об этом первый раз слышу, такой задачи не стояло. Я ведь сразу спросил, зачем там Invoke.

Говнокод среднего характера: передай в конструктор класса Class1 ссылку на форму Form1, запомни в поле класса _form1 и вызывай _form1.Invoke()
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007437
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если делать по-нормальному - надо сделать хотя бы чтобы Class1 издавал события, а Form1 их обрабатывала и меняла свои контролы. Тогда это будет нормальная отвязка класса от конкретного потребителя.
Еще более нормально - работать с моделью и привязками... но разберись пока с этим.
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007467
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В спойлере код.
Сделал событие изменения текста кнопки и текстового блока.
Т.к. клик идет на кнопке, то ее название меняется, а при попытке поменять текст текстового блока получаю ту же ошибку, что объект был создан в другом потоке.
Пробовал handlerFunc1 changeText делать нестатическим и передавать объект class1 из Program при создании Form1 в качестве параметра, но ситуация не меняется.
Form1:
Код: 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.
namespace Form1
{
	public partial class Form1 : Form
	{
		public Class1 class1;

		public Form1()
		{
			InitializeComponent();
		}

		public void changeButtonText(string txt)
		{
			button1.Text = txt;
			richTextBox1.Text = txt;
		}

		private async void button1_Click_1(object sender, EventArgs e)
		{
			class1 = new Class1();
			await class1.Connect();
		}
	}
}


Class1:
Код: 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.
namespace Form1
{
	public class Class1
	{
		public HubConnection connection;
		public IHubProxy hubProxy;

		public delegate void handlerFunc1(string message);
		public static event handlerFunc1 changeText;

		public async Task Connect()
		{
			connection = new HubConnection("...");
			hubProxy = connection.CreateHubProxy("...");
			hubProxy.On<object>("...", (data) =>
				{
					MessageBox.Show("OK");
					changeText("22222");
				}
			);

			await connection.Start();

			await Auth();
		}

		private async Task Auth()
		{
			await hubProxy.Invoke("...", Credentials);
		}
	}
}


Program:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
namespace Form1
{
	static class Program
	{
		[STAThread]
		static void Main()
		{
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);

			Form1 form1 = new Form1();
			Class1 class1 = new Class1();

			Class1.changeText += form1.changeButtonText;

			Application.Run(form1);
		}
	}
}

...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007472
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так текст меняется, но только со второго раза.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
        delegate void textboxChangeText(string txt);

        public void changeButtonText(string txt)
        {
            button1.Text = txt;
            if (InvokeRequired)
            {
                BeginInvoke(new textboxChangeText(changeButtonText), new object[] { txt });
            }
            else
            {
                richTextBox1.Text = txt;
            }
        }



Есть ли принципиальная разница, делать событие статическим или нет?
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007480
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не надо делать событие статическим
Андрей Il
Так текст меняется, но только со второго раза.
это кто придумал? ты осознаёшь, что тут вообще происходит?
Андрей Il
Код: c#
1.
BeginInvoke(new textboxChangeText(changeButtonText), new object[] { txt });

Просто напиши
Код: c#
1.
2.
3.
4.
Invoke(() => {
	button1.Text = txt;
	richTextBox1.Text = txt;
});

не надо мудрить
...
Рейтинг: 0 / 0
Проблема с вызовом await Invoke из другого класса
    #40007492
Андрей Il
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Смотрел по документациям и примерам.

Так работает:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
delegate void textboxChangeText(string txt);

public void changeButtonText(string txt)
{
	if (InvokeRequired)
	{
		BeginInvoke(new textboxChangeText(changeButtonText), new object[] { txt });
	}
	else
	{
		button1.Text = txt;
		richTextBox1.Text = txt;
	}
}


И так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
public void changeButtonText(string txt)
{
	Invoke((Action)(() => {
		button1.Text = txt;
		richTextBox1.Text = txt;
	}));
}
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Проблема с вызовом await Invoke из другого класса
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]