#c# #multithreading #static #delegates
#c# #многопоточность #статический #делегаты
Вопрос:
У меня есть статический класс с именем Service, который запускает новый поток, чтобы продолжать прослушивать сообщения от другого процесса. В этом классе я управляю списком делегатов, которые необходимо вызывать при получении сообщения. Некоторые методы этих делегатов должны выполняться в основном потоке.
Например, если бы я создал угрозу в какой-либо форме, я мог бы просто сделать
this.Invoke(@delegate, new object[] { messageReceived });
Но я не могу этого сделать, потому что я в статическом классе. Итак, я попытался сделать так:
@delegate.Invoke(messageReceived);
Но это не работает, потому что не изменяет подпроцесс, в котором выполняется метод (он выполняется из созданной мной угрозы, а не из основной).
Как я могу сделать?
Спасибо!
Комментарии:
1. BeginInvoke, а не Invoke .
Ответ №1:
Измените свой static
класс, чтобы он принимал параметр.
Передайте вашу this
переменную в качестве параметра вашему static
классу.
Ответ №2:
Почему вы не используете систему.Многопоточность.Класс SynchronizationContext? Если вы собираетесь в будущем перейти на WPF, полезно изучить это. Контекст синхронизации — это стандартный переносимый метод для обработки межпоточных сообщений. Для каждой системы есть версия … из System.Веб, Windows forms, wpf, а также пользовательский контекст синхронизации.
public static class MyClass
{
public static void MyFunction(MyObject messageReceived )
{
// Call this stuff from non-gui thread.
SynchronizationContext syncContext = SynchronizationContext.Current;
syncContext.Send(MyMethod, param);
// You can also use SyncContext.Post if you don't need to wait for completion.
syncContext.Post(MyMethod, param);
}
private static void MyMethod(object state)
{
MyObject myObject = state as MyObject;
... do my stuff into the gui thread.
}
// Using anonymous delegates you can also have a return value using Send.
public static int MyFunctionWithReturnValue(MyObject parameter)
{
int result = 0;
SynchronizationContext.Current.Post(delegate (object p)
{
result = parameter.DoSomething()
}, null);
return resu<
}
}
Ответ №3:
Ваша проблема может быть решена с помощью SynchronizationContext
. В двух словах, захватите SynchronizationContext
поток пользовательского интерфейса и используйте Post
метод для публикации элемента в цикле сообщений графического интерфейса. Нет необходимости писать больше, так как вы можете найти отличную статью здесь
Комментарии:
1. Спасибо за ссылку! действительно лучше, чем любое «полное» объяснение [да, я знаю, что этому 11 лет …]
Ответ №4:
Извините, я забыл это в своем вопросе. Я также хотел избежать использования System.Windows.Формирует классы в моем статическом классе.
Самый простой способ, который я нашел, это вызвать метод Invoke из объекта delegate (как я пробовал раньше, и это не сработало). И в методе делегата сделайте это:
if (this.InvokeRequired)
this.Invoke(MethodWhichDoesRealStuff, new object[] { message });
else
MethodWhichDoesRealStuff(message);
Я также заметил, что мне на самом деле не нужно было управлять списком делегатов в моем классе. Событие делает именно это для меня.