Возьмите метод System.Windows.Forms.Control.Invoke (метод делегата)
Почему это дает ошибку времени компиляции:
string str = "woop";
Invoke(() => this.Text = str);
// Error: Cannot convert lambda expression to type 'System.Delegate'
// because it is not a delegate type
Тем не менее, это отлично работает:
string str = "woop";
Invoke((Action)(() => this.Text = str));
Когда метод ожидает простого делегата?
Invoke(()=>DoStuff)
но все равно получил ошибку. Проблема заключалась в том, что я использовал неявное «это». Для того, чтобы заставить его работать внутри элемента управления вы должны быть четко:this.Invoke(()=>DoStuff)
.Устали снова и снова использовать лямбды?
источник
Lambda<T>
класса есть вызываемый метод преобразования идентичностиCast
, который возвращает все, что было передано (Func<T, T>
). ТеперьLambda<T>
объявляется ,Lambda<Func<int, string>>
что означает , если передатьFunc<int, string>
вCast
метод, он возвращаетсяFunc<int, string>
обратно, так какT
в этом случае являетсяFunc<int, string>
.В девяти десятых случаях люди получают это, потому что они пытаются маршалироваться в поток пользовательского интерфейса. Вот ленивый способ:
Теперь, когда он напечатан, проблема исчезла (ответ Скита), и у нас есть очень сжатый синтаксис:
Для бонусных баллов вот еще один совет. Вы бы не сделали этого для пользовательского интерфейса, но в тех случаях, когда вам нужно заблокировать SomeMethod до его завершения (например, ввод-вывод запроса / ответа, ожидание ответа), используйте WaitHandle (qv msdn WaitAll, WaitAny, WaitOne).
Обратите внимание, что AutoResetEvent является производным от WaitHandle.
И последний совет, потому что все может запутаться: WaitHandles останавливает поток. Вот что они должны делать. Если вы попытаетесь выполнить маршалинг в поток пользовательского интерфейса, пока он у вас остановлен , ваше приложение зависнет. В этом случае (а) следует провести серьезный рефакторинг и (б) в качестве временного взлома вы можете подождать вот так:
источник
System.Windows.Threading.Dispatcher.CurrentDispatcher
вернет диспетчер ТЕКУЩЕГО потока - т.е. если вы вызовете этот метод из потока, который не является потоком пользовательского интерфейса, код не будет запущен в потоке пользовательского интерфейса.Питер Вон. ты мужик. Развивая вашу концепцию немного дальше, я придумал эти две функции.
Я помещаю эти две функции в свое приложение Form, и я могу звонить из фоновых рабочих, как это
Может быть, немного ленив, но мне не нужно настраивать функции, выполняемые работником, что очень удобно в таких случаях, как этот
По сути, получить некоторые IP-адреса из графического интерфейса DataGridView, проверить их связь, установить для результирующих значков зеленый или красный цвет и повторно включить кнопки в форме. Да, это "parallel.for" в фоновом работнике. Да, это ОЧЕНЬ накладные расходы, но они незначительны для коротких списков и гораздо более компактного кода.
источник
Я попытался построить это на ответе @Andrey Naumov . Может быть, это небольшое улучшение.
Где параметр типа
S
- это формальный параметр (входной параметр, минимально необходимый для определения остальных типов). Теперь вы можете назвать это так:У вас могут быть дополнительные перегрузки для одного
Action<S>
иExpression<Action<S>>
того же класса. Для других встроенных типов делегатов и выражений вам придется писать отдельные классы, напримерLambda
,Lambda<S, T>
иLambda<S, T, U>
т. Д.Преимущество этого я вижу перед оригинальным подходом:
На одну спецификацию типа меньше (необходимо указать только формальный параметр).
Это дает вам свободу использовать его против любого
Func<int, T>
, а не только тогда, когдаT
, скажемstring
, как показано в примерах.Сразу поддерживает выражения. В более раннем подходе вам придется снова указать типы, например:
для выражений.
Расширение класса для других типов делегатов (и выражений) так же громоздко, как и выше.
В моем подходе вы должны объявлять типы только один раз (что тоже на один меньше для
Func
s).Еще один способ реализовать ответ Андрея - это не совсем общий
Итак, все сводится к:
Это еще меньше, но вы теряете определенную безопасность типов, и я думаю, этого не стоит.
источник
Немного поздно на вечеринку, но вы также можете использовать это
источник
источник
Играя с XUnit и Fluent Assertions, можно было использовать эту встроенную возможность, что я считаю действительно крутым.
Перед
После
источник