0

这是我的问题:我有一个应用程序必须进行数百万次计算(这是为了发表一篇科学论文)。

所以为了加快计算速度,我学到了一点关于线程的知识并做了这个:

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我有一个名为的方法defineListOfSameDonInparticule:,其中有:

[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 increaseProgressionMeterByOne]向我的应用程序委托发送了一条消息,该委托又将 incrementBy:1 发送到我的进度条

但是我所有的线程都被同时发生的数百万次计算使用,所以 UI 冻结,我的 progressBar 没有前进。

需要注意的是:我的进度条在程序的其他不使用多线程的部分工作正常

有没有办法强制更新用户界面?或者您对如何解决这个问题有任何想法?

我知道更新 UI 会减慢应用程序的速度,但对于应用程序的目标用户来说,这是必要的!

非常感谢 !

更新 :

这是在 AppDelegate 中更新 UI 的代码

- (void)increaseProgressionMeterByOne {
    [progressBar incrementBy:1];
}
4

2 回答 2

1

安德鲁的回答显示了如何包装对方法的调用以在主线程上执行它。

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 来处理它。

于 2014-05-30T15:45:45.907 回答
1

您需要将 UI 更新包装在dispatch_async(dispatch_get_main_queue(), ^{});. UIKit 不是线程安全的。

于 2014-05-27T16:29:17.277 回答