首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >正确使用中央调度-启动、挂起、恢复、取消线程?

正确使用中央调度-启动、挂起、恢复、取消线程?
EN

Stack Overflow用户
提问于 2012-05-16 11:56:55
回答 1查看 3.6K关注 0票数 2

我刚刚建立了一个小的测试项目来测试中央调度中心。我需要使用串行队列。在运行后台任务时,我需要完全挂起、恢复或取消线程。以及:我如何知道创建的队列是否已经在运行?(然后我必须重新启动它)。

这是我第一次使用多线程,所以如果我使用正确的话,能得到一些提示就太好了。我没有找到任何类似的东西,所以如果你能检查我的代码,那就太酷了。我能正确释放对象吗?还有没有进一步的改进?

非常感谢您的帮助和时间。

这是代码或link to the sample project

ViewController.m

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "ViewController.h"
#import "SVProgressHUD.h"
#import "Queue.h"

@interface ViewController (){
    Queue* queue;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    queue = [[Queue alloc] init];

    UIButton* startbutton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    [startbutton setTitle:@"Start Queue" forState:UIControlStateNormal];
    [startbutton addTarget:self action:@selector(startQueueButton:) forControlEvents:UIControlEventTouchUpInside];
    [startbutton setFrame:CGRectMake(100, 200, 100, 70)];
    [self.view addSubview:startbutton];


    UIButton* suspendbutton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    [suspendbutton setTitle:@"Stop Queue" forState:UIControlStateNormal];
    [suspendbutton addTarget:self action:@selector(suspendQueueButton:) forControlEvents:UIControlEventTouchUpInside];
    [suspendbutton setFrame:CGRectMake(250, 200, 100, 70)];
    [self.view addSubview:suspendbutton];

    UIButton* resumebutton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    [resumebutton setTitle:@"Resume Queue" forState:UIControlStateNormal];
    [resumebutton addTarget:self action:@selector(resumeQueueButton:) forControlEvents:UIControlEventTouchUpInside];
    [resumebutton setFrame:CGRectMake(400, 200, 170, 70)];
    [self.view addSubview:resumebutton];

    UIButton* cancelbutton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    [cancelbutton setTitle:@"Cancel Queue" forState:UIControlStateNormal];
    [cancelbutton addTarget:self action:@selector(cancelQueueButton:) forControlEvents:UIControlEventTouchUpInside];
    [cancelbutton setFrame:CGRectMake(600, 200, 170, 70)];
    [self.view addSubview:cancelbutton];

}

-(void) startQueueButton:(UIButton*) button{    
    NSLog(@"---> startQueueButton");
    [queue start];
}

-(void) suspendQueueButton:(UIButton*) button{
    NSLog(@"---> suspendQueueButton");
    [queue suspend];
}


-(void) resumeQueueButton:(UIButton*) button{
    NSLog(@"---> resumeQueueButton");
    [queue resume];
}

-(void) cancelQueueButton:(UIButton*) button{
    NSLog(@"---> cancelQueueButton");
    [queue cancel];
}



- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end

Queue.m

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "Queue.h"
#import "SVProgressHUD.h"

@interface Queue (){
    dispatch_queue_t queue;
}

@end

@implementation Queue


-(void) start{
    NSLog(@"Queue - start");    

    int count = 1000;

     // SERIAL QUEUE ======================================
     // =======================================================================

    queue = dispatch_queue_create("com.jf.TestQueue", NULL);

    [SVProgressHUD showWithStatus:@"Rendering..."];


    for(int i = 0; i < count; i++) 
    {
        dispatch_async(queue, ^{

            NSLog(@"--> ASYNC %d", i);

           // rendering complete, get back to main queue
           dispatch_async(dispatch_get_main_queue(), ^
              {
                 NSLog(@"--> Image rendered: %d", i);

                  if (i == count-1) {
                      NSLog(@"EndRenderingQueue");

                      [SVProgressHUD dismiss];
                  }
              });
        });
    }

    dispatch_release(queue);    // even under ARC we have to release it    
}


-(void) suspend{

    NSLog(@"Queue - suspend");

    if (queue) {
        NSLog(@"___suspend");
        dispatch_suspend(queue);
    }
}

-(void) resume{
    NSLog(@"Queue - resume");
    if (queue) {
        dispatch_resume(queue);
    }
}
-(void) cancel{
    NSLog(@"Queue - cancel");

    if (queue) {
        dispatch_suspend(queue);
        //dispatch_release(queue);  // if it´s uncommented, it crashes. How to release it securely?
        queue = nil;

        [SVProgressHUD dismiss];

    }

}

@end
EN

回答 1

Stack Overflow用户

发布于 2012-05-16 21:21:58

我相信一般的做法是,你通常不会挂起后台队列,除非你确实需要这样做(例如,如果你创建的队列被允许运行后续的块,那么你在另一个队列中的一些操作就不能正常/很好地操作)。在某些情况下,您可能希望这样做,但通常您不必为此担心。我们大多数人都在创建队列,使用它们,当我们不积极地使用它们时,让它们处于空闲状态(尽管不是挂起它们),当我们再次需要后台队列时,继续使用它,当我们都使用完它们时(即,在可预见的未来,我们不需要后台队列),我们释放它们,在这一点上,我们不再使用旧的队列指针。

至于如何知道它是否被挂起,我认为除了dispatch_debug()之外,没有其他方法。您正在挂起它,所以您已经知道它是否挂起了,所以可以编写自己的包装器来跟踪您自己的挂起计数。通常,我认为您会在必要时暂停,然后在冲突的前台(或其他)任务完成时恢复,并且可以安全地再次使用后台队列。在这种情况下,确定它是否被挂起更多的是一个学术问题。

为什么需要挂起后台队列?您试图解决的业务逻辑问题是什么?顺便说一句,我假设您知道在该队列中运行的当前块不受挂起的影响。我认为只有排队的(先前排队和等待,或随后排队的)块才会受到影响,而不是当前块。

就你的代码而言,你是在start方法中释放你的队列(例如,一旦队列被清空,它将被异步释放)。只有在不再需要队列的情况下,才应该这样做。如果调用dispatch_release() (即不使用ARC),则将来对队列变量的任何使用都是不可靠的(当然,除非dispatch_release()是与dispatch_retain()一起完成的)。一旦您最终释放它,您甚至可能希望将队列变量设置为nil,这样您就不会想要使用它。坦率地说,我感到惊讶的是,鉴于您在start方法中执行了dispatch_release(),并且在已经释放队列的情况下能够调用dispatch_suspend()dispatch_resume()而没有出现任何严重异常(除非偶然情况下,提交给该队列的原始代码块尚未完成)。

总之,在您开始追求挂起队列之前(我不确定您是出于好奇心,还是有一些迫切的业务问题需要解决),我建议您先用业务逻辑和相关代码来澄清您的问题。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10617993

复制
相关文章
Java中常见的异常类型
类格式错误。当Java虚拟机试图从一个文件中读取Java类,而检测到该文件的内容不符合类的有效格式时抛出。
JanYork_简昀
2022/04/02
2.3K0
Java---线程多(工作内存)和内存模型(主内存)分析
转载自 https://www.cnblogs.com/chihirotan/p/6486436.html
allsmallpig
2021/02/25
2K0
JDK源码解析之 java.lang.Error
错误。是所有错误的基类,用于标识严重的程序运行问题。这些问题通常描述一些不应被应用程序捕获的反常情况。
栗筝i
2022/12/01
6280
Java-线程中的异常
给出以下例子,我想问题是线程t1运行期间抛出的异常能够被捕获吗?(这是一个相当好的问题~)
Fisherman渔夫
2020/02/19
1.5K0
cdn节点访问失败,源站测试正常,节点异常?
cdn节点测试访问异常,出现空响应,直接访问源站正常,这里看起来像是节点出现异常。
任雯霄
2020/12/30
3.8K0
java主线程捕获子线程中的异常
如果想要在主线程中捕获子线程的异常,我们需要使用ExecutorService,同时做一些修改。
Java架构师必看
2021/05/14
3K0
java主线程捕获子线程中的异常
java高级用法之:JNA中的Function
在JNA中,为了和native的function进行映射,我们可以有两种mapping方式,第一种是interface mapping,第二种是direct mapping。虽然两种方式不同,但是在具体的方法映射中,我们都需要在JAVA中定义一个和native方法进行映射的方法。
程序那些事
2022/05/17
5710
Java面试系列9
java中的保留字,现在没有在java中使用。 ✎二、必须要知道的运行时异常 ArithmeticException 是出现异常的运算条件时,抛出此异常。 例如,一个整数“除以零”时,抛出此类
Java帮帮
2018/03/19
2K0
winform 多线程中ShowDialog()步骤无效的解决办法
private void Form1_Load(object sender, EventArgs e) { Thread thread = new Thread(remind); thread.IsBackground = true; thread.Start(); } private void remind() { while (true) { string h = "0"; string m = "23";
跟着阿笨一起玩NET
2018/09/19
1.3K0
Java跨语言调用,使用JNA访问Java外部接口
先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即可。首先看下JNI调用C/C++的过程,注意写程序时自下而上,调用时自上而下。
朝雨忆轻尘
2019/06/18
4.6K0
java高级用法之:JNA中的Structure
前面我们讲到了JNA中JAVA代码和native代码的映射,虽然可以通过TypeMapper来将JAVA中的类型和native中的类型进行映射,但是native中的数据类型都是基础类型,如果native中的数据类型是复杂的struct类型该如何进行映射呢?
程序那些事
2022/05/09
1.9K0
java高级用法之:JNA中的Structure
前面我们讲到了JNA中JAVA代码和native代码的映射,虽然可以通过TypeMapper来将JAVA中的类型和native中的类型进行映射,但是native中的数据类型都是基础类型,如果native中的数据类型是复杂的struct类型该如何进行映射呢?
程序那些事
2022/05/17
6640
java高级用法之:JNA中的Function
在JNA中,为了和native的function进行映射,我们可以有两种mapping方式,第一种是interface mapping,第二种是direct mapping。虽然两种方式不同,但是在具体的方法映射中,我们都需要在JAVA中定义一个和native方法进行映射的方法。
程序那些事
2022/05/06
1K0
java高级用法之:JNA中的回调
什么是callback呢?简单点说callback就是回调通知,当我们需要在某个方法完成之后,或者某个事件触发之后,来通知进行某些特定的任务就需要用到callback了。
程序那些事
2022/05/10
1.5K0
java中的异常总结
一般面试中java Exception(runtimeException )是必会被问到的问题
哲洛不闹
2018/09/19
1.4K0
Java多线程中的内存可见性
分为主内存和线程内存,当线程与其他线程共享一个变量时,便会把主内存的变量复制到线程内存中去。当发生对变量的修改时,会同步到主内存,主内存再同步到其他线程内存中去。
zhangheng
2020/04/28
5020
异常、线程
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/100192.html原文链接:https://javaforall.cn
全栈程序员站长
2022/06/29
7660
异常、线程
RuntimeException和Exception区别
Java设置了异常,旨在鼓励将方法中可能出现的异常告知给使用此方法的程序员(你和我!)。当然了,这种方法是比较优雅的,让我们确切的知道是在哪里出了错,并提供了异常捕获。本篇文章主要对Java中的异常进行介绍与区分。
全栈程序员站长
2022/09/15
1.1K0
RuntimeException和Exception区别
WPF中UI元素跨线程访问
dotnet中线程资源独占UI元素,不能跨线程访问,可以通过Dispatcher.Invoke的方式调用,但实际处理还是UI线程中,任务量比较大的数据会增加线程的处理压力。 其实还有一种做法,可以通过设置UI元素为只读的方式,跨线程访问。 如BitmapSource跨线程访问,可以调用Freeze设置元素为只读模式。 Aforge.net跨线程传递图像资源,如下:
sofu456
2019/07/09
1.1K0
java高级用法之:JNA中的回调
什么是callback呢?简单点说callback就是回调通知,当我们需要在某个方法完成之后,或者某个事件触发之后,来通知进行某些特定的任务就需要用到callback了。
程序那些事
2022/05/17
8950

相似问题

JNA无效内存访问

13

JNA:无效内存访问

11

JNA:无效内存访问

18

JNA中的无效内存访问

16

映射JNA中的COM接口方法无效内存访问异常

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文