Гость
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Проблема с вызовом await Invoke из другого класса / 22 сообщений из 22, страница 1 из 1
10.10.2020, 17:35
    #40007270
Андрей Il
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Здравствуйте.

Есть основная форма, которая запускается через:
Код: 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
10.10.2020, 18:03
    #40007275
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Опуская тот момент, что от этого кода кровь идет из глаз, но допустим он тестовый...

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

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

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

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

Андрей Il
Код тестовый.)
Даже для тестового кода не надо говнокодить синхронный вызов асинхронных методов, да еще в конструкторе. Сделай нормальные асинхронные методы и вызывай с await-ом и не будет проблем.
...
Рейтинг: 0 / 0
10.10.2020, 18:35
    #40007285
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Андрей Il
Как правильно сделать, чтобы вызовы работали в любом классе?
ожидать окончания асинхронных вызовов с помощью await
...
Рейтинг: 0 / 0
10.10.2020, 21:25
    #40007317
Андрей Il
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
В 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
10.10.2020, 22:29
    #40007340
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Андрей Il
Внес
Андрей Il
Убрал
Андрей Il
изменил
Я не буду собирать это из непонятных кусков, покажи код, который получился (класс формы и Class1)
...
Рейтинг: 0 / 0
11.10.2020, 11:22
    #40007403
Андрей Il
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
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
11.10.2020, 11:37
    #40007407
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Еще раз. Убери Form.Invoke и наследование Class1 от Form
...
Рейтинг: 0 / 0
11.10.2020, 11:43
    #40007409
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Я бы еще для чистоты эксперимента сделал вызов не в Form1_Load, а по кнопке, потому что в изначальном коде метод Connect, как я понимаю, тоже вызывается не из Form1_Load
...
Рейтинг: 0 / 0
11.10.2020, 12:56
    #40007418
Андрей Il
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Shocker.Pro
Еще раз. Убери Form.Invoke и наследование Class1 от Form

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

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

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


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

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

Говнокод среднего характера: передай в конструктор класса Class1 ссылку на форму Form1, запомни в поле класса _form1 и вызывай _form1.Invoke()
...
Рейтинг: 0 / 0
11.10.2020, 15:08
    #40007437
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Если делать по-нормальному - надо сделать хотя бы чтобы Class1 издавал события, а Form1 их обрабатывала и меняла свои контролы. Тогда это будет нормальная отвязка класса от конкретного потребителя.
Еще более нормально - работать с моделью и привязками... но разберись пока с этим.
...
Рейтинг: 0 / 0
11.10.2020, 19:31
    #40007467
Андрей Il
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
В спойлере код.
Сделал событие изменения текста кнопки и текстового блока.
Т.к. клик идет на кнопке, то ее название меняется, а при попытке поменять текст текстового блока получаю ту же ошибку, что объект был создан в другом потоке.
Пробовал 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
11.10.2020, 19:50
    #40007472
Андрей Il
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Так текст меняется, но только со второго раза.
Код: 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
11.10.2020, 20:30
    #40007480
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Не надо делать событие статическим
Андрей 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
11.10.2020, 21:15
    #40007492
Андрей Il
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема с вызовом await Invoke из другого класса
Смотрел по документациям и примерам.

Так работает:
Код: 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
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Проблема с вызовом await Invoke из другого класса / 22 сообщений из 22, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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