C # Вызов делегата из статического класса

#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);
  

Я также заметил, что мне на самом деле не нужно было управлять списком делегатов в моем классе. Событие делает именно это для меня.