ForEach для IEnumerables
public static class FrameworkExtensions
{
// a map function
public static void ForEach<T>(this IEnumerable<T> @enum, Action<T> mapFunction)
{
foreach (var item in @enum) mapFunction(item);
}
}
Наивный пример:
var buttons = GetListOfButtons() as IEnumerable<Button>;
// click all buttons
buttons.ForEach(b => b.Click());
Прохладный пример:
// no need to type the same assignment 3 times, just
// new[] up an array and use foreach + lambda
// everything is properly inferred by csc :-)
new { itemA, itemB, itemC }
.ForEach(item => {
item.Number = 1;
item.Str = "Hello World!";
});
Примечание:
Это не похоже Select
, потому что Select
ожидает Ваша функция возвращать что-то что касается преобразования в другой список.
ForEach просто позволяет Вам выполнять что-то для каждого из объектов без любых преобразований/манипулирования данными.
я сделал это так, я могу программировать в более функциональном стиле, и я был удивлен, что Список имеет ForEach, в то время как IEnumerable не делает.
Помещенный это в codeplex проект
Как упоминалось в других ответах, флэш-проигрыватель является однопоточным, если вы не разбиваете свою работу на отдельные фрагменты, которые могут выполняться в отдельных «кадрах ", вы увидите скачки и заикания в пользовательском интерфейсе, что, по сути, и есть то, что вы видите.
Если вы действительно должны увидеть это сообщение 12%, то этого недостаточно, чтобы аннулировать список отображения, поскольку отображение list не может обновиться до тех пор, пока работа 56% не будет завершена, вы должны явно прервать цикл естественных событий с помощью вызова validateNow ()
после того, как ваше сообщение было установлено.
Это однако это не лучший способ делать что-то, если производительность вызывает беспокойство. Вы можете обойтись судебным использованием callLater ()
, чтобы запланировать каждый фрагмент работы по очереди,
Попробуйте вызывать invalidateDisplayList () после каждого изменения индикатора выполнения. Примерно так:
Class StatusBar
{
public function set progress(value:uint):void
{
progressBar.value = value;
progressBar.invalidateDisplayList();
}
}
Flex имеет цикл аннулирования, который позволяет избежать перерисовки экрана при каждом изменении свойства. Например, если значение свойства изменяется 3 раза за один кадр, оно будет отображаться только с последним установленным значением. Вы можете принудительно перерисовать компонент, вызвав invidateDisplayList (), что означает, что updateDisplayList будет выполняться немедленно вместо ожидания следующего кадра.
ActionScript в проигрывателе Flash, как и Javascript в браузере, является псевдопоточным. То есть они однопоточные, но имеют несколько стеков выполнения. Это означает, что вы не можете «засыпать» в конкретном потоке, но вы можете создать новый стек выполнения, который откладывается на более позднее время. Гибкий способ сделать это - функция callLater. Вы также можете использовать функции setTimeout / setInterval. Или вы можете использовать объект таймера, встроенный во флеш-плеер. Или даже прослушиватель событий "ENTER_FRAME". Все это, по сути, позволит вам делать то, что вам нужно, если я прав в отношении причины ваших проблем.
Похоже, у вас есть один «поток», который выполняет большую часть вашей работы, никогда не останавливаясь, чтобы разрешить выполнение других стеков выполнения (потоков *).
Проблема может заключаться в том, что говорит PeZ, но если это не поможет, вы можете попробовать некоторые отложенные вызовы для рабочих классов. Теперь ваш процесс может выглядеть так:
(если ваш работник является компонентом UI, вы можете использовать uicomp.callLater (...), в противном случае вам нужно использовать setTimeout / timers / enter_frame для чистых классов AS3).
Glenn,
Это совсем не то, как работает потоковая обработка во Flex. Как и многие другие пользовательские интерфейсы, он имеет насос сообщений в главном потоке пользовательского интерфейса (они делают это во фреймах). Когда вы вызываете callLater(), она помещает переданный указатель функции в конец очереди насоса сообщений (на следующий кадр) и немедленно возвращается. Затем функция вызывается, когда насос сообщений закончит обработку всех предшествующих сообщений (например, щелчков мыши).
Проблема в том, что поскольку изменение свойства вызывает события пользовательского интерфейса, они помещают свои собственные сообщения в насос, который теперь приходит после вызова вашего метода, который вы поместили туда из callLater().
Flex действительно имеет несколько потоков, но они существуют по собственным причинам Adobe и поэтому не доступны пользователю. Я не знаю, есть ли способ гарантировать, что обновление пользовательского интерфейса произойдет в определенный момент, но можно вызвать callLater несколько раз, пока операция не произойдет. Начните с небольшого числа и увеличивайте его до тех пор, пока количество итераций не приведет к желаемому результату. Пример:
// Change this to a number that works... it will probably be over 1, depending on what you're doing.
private const TOTAL_CALL_COUNT:int = 5;
private var _timesCalled:int = 0;
//----------------------------------------------------------------
private function set Progress( progress:int ):void
{
progressBar.value = progress;
DoNextFunction();
}
//----------------------------------------------------------------
private function DoNextFunction():void
{
if( _timesCalled >= TOTAL_CALL_COUNT )
{
_timesCalled = 0;
Function();
}
else
{
_timesCalled++;
callLater( DoNextFunction );
}
}