AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78309419
Accepted
Askri Nguyen
Askri Nguyen
Asked: 2024-04-11 17:38:49 +0800 CST2024-04-11 17:38:49 +0800 CST 2024-04-11 17:38:49 +0800 CST

Preciso de alguns esclarecimentos sobre dispatch_queue_create e RunLoop. Compartilhando RunLoop entre eles

  • 772

Estou desenvolvendo framework iOS com Objective-C.

Eu crio um dispatch_queue_tusando dispatch_queue_create. E ligue CFRunLoopRun()para executar o runloop na fila.

Mas, parece que o dispatch_queue_t compartilhou o RunLoop. Algumas classes adicionaram um cronômetro inválido e, quando eu chamo o CFRunLoopRun(), ele travou do meu lado.

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.queue1 = dispatch_queue_create("com.queue1", DISPATCH_QUEUE_CONCURRENT);
    self.queue2 = dispatch_queue_create("org.queue2", DISPATCH_QUEUE_CONCURRENT);
}

- (IBAction)btnButtonAction:(id)sender {
    
    dispatch_async(self.queue1, ^{
        
        NSString *runloop = [NSString stringWithFormat:@"%@", CFRunLoopGetCurrent()];
        runloop = [runloop substringWithRange:NSMakeRange(0, 22)];
        NSLog(@"Queue1 %p run: %@", self.queue1, runloop);
        
        //NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:1 target:self selector:@selector(wrongSeletor:) userInfo:nil repeats:NO];
        //[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    });
    
    dispatch_async(self.queue2, ^{
        NSString *runloop = [NSString stringWithFormat:@"%@", CFRunLoopGetCurrent()];
        runloop = [runloop substringWithRange:NSMakeRange(0, 22)];
        NSLog(@"Queue2 %p run: %@", self.queue2, runloop);
        
        CFRunLoopRun();
    });
}

Algum tempo eles levam o mesmo RunLoop:

https://isstatic.askoverflow.dev/wGcv3.png

=====

Você pode ver a falha descomentando o código de NSTimer. O NSTimer foi adicionado queue1, mas ainda está em execução quando CFRunLoopRun()chamado queue2.

Eu li algumas descrições como: preciso de alguns esclarecimentos sobre fila de despacho, thread e NSRunLoop

Eles contaram que: system creates a run loop for the thread. Mas, na minha opinião, eles estão compartilhando o RunLoop.

Isso é triste para mim, pois enfrento que acontecem travamentos ao chamar CFRunLoopRun()a produção.

objective-c
  • 1 1 respostas
  • 46 Views

1 respostas

  • Voted
  1. Best Answer
    Rob
    2024-04-11T23:02:23+08:002024-04-11T23:02:23+08:00

    dr.

    Existem vários problemas com esse código de loop de execução. Mas, se a intenção fosse simplesmente executar um cronômetro em uma fila de despacho, geralmente usaríamos um cronômetro de origem de despacho , eliminando grande parte dessa confusão.


    O padrão de loop de execução típico envolve a criação de um thread dedicado, a obtenção de um loop de execução para esse thread e a chamada de um dos métodos de “execução” para girar nesse thread, processando eventos de loop de execução, como eventos de timer.

    Uma fila de despacho é uma abordagem diferente. Quando despachamos um “item de trabalho” para uma fila de despacho, essa fila buscará um thread de trabalho (aleatório) de um conjunto de threads, executará esse item de trabalho naquele thread de trabalho e, quando o item de trabalho estiver concluído, retornará esse item de trabalho thread para o pool de threads, disponibilizando-o para despachos futuros.

    Isso nos leva a várias observações sobre seu snippet de código:

    1. O envio para queue1não faz sentido. Você imprime um loop de execução, mas não “executa” nele, apenas finaliza, retornando assim o thread de trabalho ao pool de threads. Esse tópico agora está disponível para ser usado novamente em futuros despachos do GCD. Só faria sentido se você girasse nesse loop de execução com um método “run”, vinculando assim esse thread a esse loop de execução e evitando que o GCD reutilizasse esse thread.

    2. Usar uma fila simultânea neste contexto é confuso. Execute loops girando em um determinado thread. Criar uma fila simultânea para essa finalidade não faz sentido. Que trabalho será feito simultaneamente nessa fila enquanto o loop de execução gira em um dos threads de trabalho? Isso sugere um mal-entendido conceitual sobre como funcionam os loops de execução.

    3. A ideia de girar indefinidamente em um loop de execução em um thread de trabalho GCD é, de todo, imprudente. O conceito geral das filas de despacho é que elas alcançam eficiência buscando um thread de trabalho existente no pool, executando o item de trabalho e retornando esse thread ao pool. A ideia de amarrar indefinidamente um thread de trabalho é indiscutivelmente antitética à ideia motivadora por trás do GCD. Você pode fazer isso, mas geralmente evitaríamos amarrar um thread de trabalho do GCD indefinidamente.

    4. Se você estiver academicamente interessado em como funcionam os loops de execução, esta exploração é adequada. Mas se você pretendia apenas executar um cronômetro em uma fila de despacho, execute loops e NSTimeressa é a abordagem errada. Um temporizador de despacho seria muito mais simples (veja abaixo).


    Se você quiser executar algo em uma fila de despacho, geralmente não usamos NSTimer. Em vez disso, usaríamos um temporizador de despacho. Isso não requer nenhum loop de execução.

    Ao contrário de a, NSTimerprecisamos manter nossa referência forte ao cronômetro:

    @property (nonatomic, strong) dispatch_source_t timer;
    

    Então, para iniciar um cronômetro:

    - (void)startTimer {
        dispatch_queue_t queue = dispatch_queue_create("com.domain.app.timer", DISPATCH_QUEUE_SERIAL);
        self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
        dispatch_source_set_event_handler(self.timer, ^{
            // this is called when the timer fires
        });
        dispatch_resume(self.timer);
    }
    

    Para parar o cronômetro, solte-o:

    - (void)stopTimer {
        self.timer = nil;
    }
    
    • 0

relate perguntas

  • Objective-c: definir atributo como propriedade, preserva as configurações padrão

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve