Использование -
dd <- data.frame(x=c(3,4,5),id=c('A','B','C'))
foo <- function(x,a){
df <- data.frame(
"id" = character()
,"y" = numeric()
)
for(i in 1:2)
{
for(j in 1:2)
{
y<-x+i+j
df<- rbind(df, data.frame(
"id" = a
,"y" = y
)
)
}
}
# Replace with group_by, filter, max
result<-df%>%
group_by(id)%>%
filter(y == max(y))
return(result$y)
}
dd%>% mutate(t=foo(dd$x, dd$id))
Вывод
x id t
1 3 A 7
2 4 B 8
3 5 C 9
Объяснение
Вы просто должны были позаботиться о последний фрагмент result
для group_by
значений id
и выборки всех строк, которые имели максимум y
для каждой группы
Возможно, Вы могли заставить DoSyncTask запускать объект - таймер, который проверяет на значение Вашей переменной данных в некотором соответствующем интервале. После того как данные имеют значение, у Вас мог затем быть другой огонь события, чтобы сказать Вам, что данные теперь имеют значение (и отключите таймер, конечно).
Довольно ужасный взлом, но это могло работать... в теории.
Извините, это является лучшим, я могу придумать наполовину спящий. Время ложиться спать...
Я испытал некоторые затруднения в последнее время из-за совершения асинхронных звонков и событий в потоках и возврате их к основному потоку.
Я использовал SynchronizationContext для отслеживания вещи. (Псевдо) код ниже показывает то, что работает на меня в данный момент.
SynchronizationContext context;
void start()
{
//First store the current context
//to call back to it later
context = SynchronizationContext.Current;
//Start a thread and make it call
//the async method, for example:
Proxy.BeginCodeLookup(aVariable,
new AsyncCallback(LookupResult),
AsyncState);
//Now continue with what you were doing
//and let the lookup finish
}
void LookupResult(IAsyncResult result)
{
//when the async function is finished
//this method is called. It's on
//the same thread as the the caller,
//BeginCodeLookup in this case.
result.AsyncWaitHandle.WaitOne();
var LookupResult= Proxy.EndCodeLookup(result);
//The SynchronizationContext.Send method
//performs a callback to the thread of the
//context, in this case the main thread
context.Send(new SendOrPostCallback(OnLookupCompleted),
result.AsyncState);
}
void OnLookupCompleted(object state)
{
//now this code will be executed on the
//main thread.
}
Я надеюсь, что это помогает, поскольку это решило проблему для меня.
Я разработал решение асинхронного для синхронизации проблемы, по крайней мере, с помощью всех классов.NET.
Это все еще не работает с COM. Я подозреваю из-за поточной обработки STA. Событие, сгенерированное компонентом.NET, который размещает COM OCX, никогда не обрабатывается моим рабочим потоком, таким образом, я получаю мертвую блокировку на WaitOne ().
кто-то еще может ценить решение хотя :)
Вы почти получили его. Вам нужен метод DoTask для работы другого потока, таким образом, вызов WaitOne не будет препятствовать тому, чтобы работа была сделана. Что-то вроде этого:
Action<int, int> doTaskAction = t.DoTask;
doTaskAction.BeginInvoke(latitude, longitude, cb => doTaskAction.EndInvoke(cb), null);
taskDone.WaitOne();
Если Задачей является компонент WinForms, она могла бы очень знать о поточной обработке проблем и Вызывать обработчик событий на основной поток - который, кажется, то, что Вы видите.
Так, могло бы случиться так, что это полагается на случай насоса сообщения или что-то. Приложение. Выполненный имеет перегрузки, которые являются для приложений для не-GUI. Вы могли бы рассмотреть то, чтобы заставлять поток запустить и накачать, чтобы видеть, устраняет ли это проблему.
Я также рекомендовал бы использовать Отражатель, чтобы заставить взгляд на исходный код компонента выяснять то, что он делает.
Мой комментарий к ответу W Scott кажется немного загадочным после того, как я перечитал его. Таким образом позвольте мне быть более явным:
while( !done )
{
taskDone.WaitOne( 200 );
Application.DoEvents();
}
WaitOne (200) вызовет, он для возврата управления UI распараллеливает 5 раз в секунду (можно скорректировать это, как Вы желаете). DoEvents () вызов сбросит очередь событий окон (тот, который обрабатывает всю обработку событий окон как рисование, и т.д.). Добавьте двух участников к своему классу (один флаг bool, "сделанный" в этом примере и данных возврата "улица" в Вашем примере).
Это - самый простой способ получить то, что Вы хотите сделанный. (У меня есть очень похожий код в моем собственном приложении, таким образом, я знаю, что он работает),