Вызов диспетчера WPF анонимным методом

#c# #.net #wpf #delegates #dispatcher

#c# #.net #wpf #делегаты #диспетчер

Вопрос:

Я только что понял в фоновом потоке C # .Net 4.0 WPF, что это не работает (ошибка компилятора):

 Dispatcher.Invoke(DispatcherPriority.Normal, delegate()
{
    // do stuff to UI
});
  

Из некоторых примеров я выяснил, что это должно было быть приведено следующим образом: (Action)delegate() . Однако в других примерах он передается другим классам, например System.Windows.Forms.MethodInvoker .

Кто-нибудь может сказать мне, что именно не так с приведенным выше примером? Я также пытался воспроизвести это с помощью других методов, но это всегда работало без приведения:

 delegate void MyAction();
void Method1(MyAction a) {
    // do stuff
}

void Method2(Action a) {
    // do stuff
}

void Tests()
{
    Method1(delegate()
    {
        // works
    });

    Method2(delegate()
    {
        // works
    });

    Method1(() =>
    { 
        // works
    });

    Method2(() =>
    {
        // works
    });

    Method2(new Action(delegate()
    {
        // works
    }));

    new System.Threading.Thread(delegate()
    {
        // works
    }).Start();
}
  

Итак, каков наилучший (наиболее элегантный, менее избыточный) способ вызова диспетчера, и что в нем такого особенного, что делегаты должны быть приведены?

Ответ №1:

Я хотел бы указать на еще более чистый пример кода по сравнению с примером Svick, в конце концов, нам всем нравятся однострочники, не так ли?

 Dispatcher.Invoke((Action) delegate { /* your method here */ });
  

Комментарии:

1. На самом деле это комментарий, а не ответ. В нем отсутствуют все объяснения, которых требует вопрос.

2. Серви: Да, я полностью пропустил предложение, в котором парень, задающий этот вопрос, фактически отвечает на свой собственный вопрос.. извините : (

3. 1 — Я частично не согласен с Servy. Джаска, пожалуйста, отредактируй свой ответ, чтобы в нем уверенно говорилось: это самый чистый способ задействовать анонимный метод. Ваш ответ в точности отвечает на заголовок вопроса: «Вызов диспетчера WPF анонимным методом». — Спасибо вам за это.

Ответ №2:

Посмотрите на подпись для Dispatcher.Invoke() . Для этого не требуется Action или какой-либо другой конкретный тип делегата. Для этого требуется Delegate , который является общим предком всех типов делегатов. Но вы не можете преобразовать анонимный метод в этот базовый тип напрямую, вы можете преобразовать его только в некоторый определенный тип делегата. (То же самое относится к лямбдам и группам методов.)

Почему это требуется Delegate ? Потому что вы можете передавать ему делегаты, которые принимают параметры или возвращаемые значения.

Вероятно, самый чистый способ:

 Action action = delegate()
{
    // do stuff to UI
};

Dispatcher.Invoke(DispatcherPriority.Normal, action);
  

Комментарии:

1. Вы можете использовать группу методов, например Action action = myMethod;

Ответ №3:

Я использую этот:

Dispatcher.Invoke((Action)(() => YourCodeHere()));

Ответ №4:

Класс ‘Delegate’ является abstract , поэтому вы должны предоставить компилятору тип, который является производным от него. Подойдет любой класс, производный от Delegate, но действие обычно является наиболее подходящим.

Комментарии:

1.Да, но delegate {} похоже, что он уже имеет тип, производный от Delegate , поэтому ваш ответ не объясняет, зачем необходимо приведение.

2. delegate (нижний регистр) — это ключевое слово c #, а не класс. Это очень распространенная путаница.

3. @Robert, я говорил не о каком-то типе delagate (вы правы, что такого типа не существует), я говорил о выражении delegate { } , которое объявляет анонимный метод, поэтому имеет смысл думать, что выражение может быть неявно преобразовано в Delegate .

4. @svick да, но вопрос, который выводит компилятор, заключается в том, каким должен быть тип делегата вашего метода. он не может быть типа Delegate, потому что это абстрактно. вероятно, компилятору можно было бы дать немного ума для создания анонимного подкласса Delegate на основе вашего параметра и возвращаемых типов (если таковые имеются), а затем преобразовать его от вашего имени… но начиная с .NET 4, они этого не сделали. может быть, в следующий раз?

5. @Роберт, да, это была моя точка зрения, и я думаю, что это не очевидно из вашего ответа.