Objective c 在非常苛刻的应用程序上强制更新UI
这是我的问题:我有一个应用程序,它必须进行数百万次计算(这是为了发表一篇科学论文) 为了加快计算速度,我学习了一些关于线程的知识,并做了以下工作:Objective c 在非常苛刻的应用程序上强制更新UI,objective-c,multithreading,macos,cocoa,nsprogressindicator,Objective C,Multithreading,Macos,Cocoa,Nsprogressindicator,这是我的问题:我有一个应用程序,它必须进行数百万次计算(这是为了发表一篇科学论文) 为了加快计算速度,我学习了一些关于线程的知识,并做了以下工作: dispatch_queue_t myFirstQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group
dispatch_queue_t myFirstQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, myFirstQueue, ^{
[Magic defineListOfSameDonInParticule:sharedData.particle];
NSMutableDictionary *results = [Magic
meanResultForSameDonInParticule:sharedData.particle];
});
在Magic.m
中,我有一个名为definelistofsamedoninparticle:
的方法,其中有:
[particule.donorsList enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
usingBlock: ^(id keyA, Molecule *alpha, BOOL *stop){
[particule.donorsList enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
usingBlock: ^(id keyB, Molecule *beta, BOOL *stop2){
if ([alpha isNotEqualTo:beta]) {
float distance = [self distanceBetweenMolecule:alpha
andMolecule:beta];
[alpha.closestSame setObject:[NSNumber numberWithFloat:distance]
forKey:beta.molID];
[appDelegate increaseProgressionMeterByOne];
}
}];
在这段代码中,我有一个[appDelegate IncrementProgressionMeterByone]
,它向我的应用程序代理发送一条消息,而我的应用程序代理又向我的进度条发送incrementBy:1
但是我所有的线程都被同时发生的数以百万计的计算所使用,因此UI冻结,我的progressBar无法前进
需要注意的是:我的进度条在不使用多线程的程序的其他部分工作正常
有没有办法强制更新UI?或者你对如何解决这个问题有什么想法
我知道更新UI会减慢应用程序的速度,但这对于应用程序的目标用户来说是必要的
非常感谢
更新:
下面是更新AppDelegate中UI的代码
- (void)increaseProgressionMeterByOne {
[progressBar incrementBy:1];
}
您需要在
dispatch\u async(dispatch\u get\u main\u queue(),^{})中包装UI更新代码> Andrew的回答显示了如何包装对方法的调用,以便在主线程上执行它
dispatch_async(dispatch_get_main_queue(), ^
{
[appDelegate increaseProgressionMeterByOne];
});
或者,如果您希望能够轻松地从不同线程安全地调用此方法,可以通过执行以下操作直接在方法本身中执行GCD调用:
- (void)increaseProgressionMeterByOne
{
if([NSThread isMainThread])
{
[progressBar incrementBy:1];
}
else
{
dispatch_async(dispatch_get_main_queue(), ^
{
[progressBar incrementBy:1];
});
}
}
如果您的方法看起来像这样,您可以从任何线程安全地调用它,它将自动留在主线程上,或者使用GCD进入主线程。您能显示更新UI的代码吗?你确定要在主线程上执行吗?你的代理回调发生在后台,所以我怀疑你可能不是。是的,问题正是我所想的。你只需要在主线程上执行UI更新。虽然同样的注意事项可能适用,但这个问题是关于Cocoa和AppKit的,而不是UIKit。我理解这意味着我必须始终在主线程上更新UI,但有没有办法确保UI在主线程上获得DIB?@TheTom你这是什么意思?我做到了,但是,每当我计算大的数字时,我的UI仍然冻结。甚至我点击的按钮也会一直保持在“开”的位置,直到所有计算结束